Section 8.7
Section 8.7
If there are fewer initializers for an array than the specified size, the others will be zero for external, static
and automatic variables. It is an error to have too many initializers. There is no way to specify repetition of an
initializer, nor to initialize an element in the middle of an array without supplying all the preceding values as
well.
Character arrays are a special case of initialization; a string may be used instead of the braces
and commas notation:
char pattern = "ould";
Recursion may provide no saving in storage, since somewhere a stack of the values being
processed must be maintained. Nor will it be faster. But recursive code is more compact, and
often much easier to write and understand than the non-recursive equivalent. Recursion is
especially convenient for recursively defined data structures like trees
Names may be undefined with #undef, usually to ensure that a routine is really a function, not
a macro:
#undef getchar
int getchar(void) { ... }
There is one difference between an array name and a pointer that must be kept in mind. A
pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable;
constructions like a=pa and a++ are illegal.
C is consistent and regular in its approach to address arithmetic; its integration of pointers,
arrays, and address arithmetic is one of the strengths of the language. Let us illustrate by
writing a rudimentary storage allocator. There are two routines. The first, alloc(n), returns a
pointer to n consecutive character positions, which can be used by the caller of alloc for
storing characters. The second, afree(p), releases the storage thus acquired so it can be reused
later. The routines are ``rudimentary'' because the calls to afree must be made in the
opposite order to the calls made on alloc. That is, the storage managed by alloc and afree
is a stack, or last-in, first-out. The standard library provides analogous functions called malloc
and free that have no such restrictions; in Section 8.7 we will show how they can be
implemented.
The easiest implementation is to have alloc hand out pieces of a large character array that we
will call allocbuf. This array is private to alloc and afree. Since they deal in pointers, not
array indices, no other routine need know the name of the array, which can be declared static
in the source file containing alloc and afree, and thus be invisible outside it. In practical
implementations, the array may well not even have a name; it might instead be obtained by
calling malloc or by asking the operating system for a pointer to some unnamed block of
storage.
The other information needed is how much of allocbuf has been used. We use a pointer,
called allocp, that points to the next free element. When alloc is asked for n characters, it
checks to see if there is enough room left in allocbuf. If so, alloc returns the current value
of allocp (i.e., the beginning of the free block), then increments it by n to point to the next
free area. If there is no room, alloc returns zero. afree(p) merely sets allocp to p if p is
inside allocbuf.
Pg-84 ADDRESS ARITHMETIC- FULL TOPIC
Any pointer can be cast to void * and back again without loss of information.
increments len, not p, because the implied parenthesization is ++(p->len). Parentheses can be
used to alter binding: (++p)->len increments p before accessing len,
struct {
int len;
char *str;
} *p;
Don't assume, however, that the size of a structure is the sum of the sizes of its members.
Because of alignment requirements for different objects, there may be unnamed ``holes'' in a
structure. Thus, for instance, if a char is one byte and an int four bytes, the structure
struct {
char c;
int i;
};
might well require eight bytes, not five. The sizeof operator returns the proper value.
struct tnode { /* the tree node: */
char *word; /* points to the text */
int count; /* number of occurrences */
struct tnode *left; /* left child */
struct tnode *right; /* right child */
}; ----- self referential function
typedef int Length; makes the name Length a synonym for int
unions value are retrieved same as pointers (. And ->)
A union may only be initialized with a value of the type of its first member; thus union u
described above can only be initialized with an integer value.
Pg 126 Table and below string examples
void *malloc(size_t n) pg --136
returns a pointer to n bytes of uninitialized storage,
void *calloc(size_t n, size_t size)
returns a pointer to enough free space for an array of n objects of the specified size, or NULL if
the request cannot be satisfied. The storage is initialized to zero.