1. A #define line defines a symbolic name or symbolic constant to be a particular string of characters: (P14)
#define name replacement text
Notice that there is no semicolon at the end of a #define line.
2. getchar() reads the next input character from a text stream and returns that as its value. That is, after (P15)
c = getchar()
the variable c contains the next character of input.
3. (Call by value) The main distinction is that in C the called function cannot directly alter a variable in the calling function; it can only alter its private, temporary copy. (P27)
4. automatic variables
external variables
In fact, common practice is to place definitions of all external variables at the beginning of the source file, and then omit all extern declarations. (P33)
5. "definition" refers to the place where the variable is created or assigned storage;
"declaration" refers to the places where the nature of the variable is stated but no storage is allocated. (P33)
6. Precedence and associativity of operators (P53)
Operators | Associativity |
( ) [ ] -> . | left to right |
! ~ ++ -- + - * & (type) sizeof | right to left |
* / % | left to right |
+ - | left to right |
<< >> | left to right |
< <= > >= | left to right |
== != | left to right |
& | left to right |
^ | left to right |
| | left to right |
&& | left to right |
|| | left to right |
?: | right to left |
= += -= *= /= %= &= ^= |= <<= >>= | right to left |
, | left to right |
7. The value of *t++ is the character that t pointed to before t was incremented; the postfix ++ doesn't change t until after this character has been fetched. (P105)
/* strcpy: copy t to s; pointer version 3 */
void strcpy(char *s, char *s)
{
while (*s++ = *t++)
;
}
8. In fact, the pair of expressions (P106)
*p++ = val; /* push val onto stack */
val = *--p; /* pop top of stack into val */
The first is similar to *p = val, p++; the second expression associativity is right to left.
In the same way, *p->str fetches whatever str points to; *p->str++ increments str after accessing whatever it points to (just like *s++); (*p->str)++ increments whatever str points to; and *p++->str increments p after accessing whatever str points to. (P132)
9. # define NKEYS (sizeof keytab / sizeof keytab[0])
or #define NKEYS (sizeof keytab / sizeof(struct key))
A sizeof can not be used in a #if line, because the preprocessor does not parse type name. But the expression in the #define is not evaluated by the preprocessor, so the code here is legal. (P135)
10. Besides purely aesthetic issues, there are two main reasons for using typedefs. The first is to parameterize a program against portability problems. If typedefs are used for data types that may be machine-dependent, only the typedefs need change when the program is moved. One common situation is to use typedef names for various integer quantities, then make an appropriate set of choices of short, int, and long for each host machine. Types like size_t and ptrdiff_t from the standard library are examples.
The second purpose of typedefs is to provide better documentation for a program-- a type called Treeptr may be easier to understand than one declared only as a pointer to a complicated structure. (P147)
11. In effect, a union is structure in which all members have offset zero from base, the structure is big enough to hold the "widest" member, and the alignment is appropriate for all of the types in the union.
A union may only be initialized with a value of the type of its first member. (P148)
12. A bit-field, or filed for short, is a set of adjacent bits within a single implementation-defined storage unit that we will call a "word". The syntax of field definition and access is based on structures. (P149)
Almost everything about fields is implementation-dependent. Whether a field may overlap a word boundary is implementation-defined. Fields need not be named; unnamed fields( a colon and width only) are used for padding. The special width 0 may be used to force alignment at the next word boundary. (P150)