0% found this document useful (0 votes)
30 views2 pages

Section 8.7

This document discusses several key concepts in C programming including array initialization, character arrays, recursion, pointer arithmetic, structures, unions, and dynamic memory allocation. It explains that arrays can be initialized with fewer elements than the size which will zero out the remaining elements. Character arrays can use a string initialization shorthand. Recursion provides more compact code but no efficiency benefits. Pointer arithmetic treats arrays and pointers equivalently. Structures and unions organize data, while dynamic memory functions like malloc and calloc allocate memory at runtime.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views2 pages

Section 8.7

This document discusses several key concepts in C programming including array initialization, character arrays, recursion, pointer arithmetic, structures, unions, and dynamic memory allocation. It explains that arrays can be initialized with fewer elements than the size which will zero out the remaining elements. Character arrays can use a string initialization shorthand. Recursion provides more compact code but no efficiency benefits. Pointer arithmetic treats arrays and pointers equivalently. Structures and unions organize data, while dynamic memory functions like malloc and calloc allocate memory at runtime.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 2

PL

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";

is a shorthand for the longer but equivalent

char pattern[] = { 'o', 'u', 'l', 'd', '\0' };

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) { ... }

a[i] can also be written as


*(a+i). In evaluating a[i],

C converts it to *(a+i) immediately; the two forms are


equivalent. Applying the operator & to both parts of this equivalence, it follows that &a[i] and
a+i are also identical: a+i is the address of the i-th element beyond a. As the other side of this
coin, if pa is a pointer, expressions might use it with a subscript; pa[i] is identical to *(pa+i).

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.

Pg-98 5.11 Pointers to Functions


A structure declaration that is not followed by a list of variables reserves no storage; it merely
describes a template or shape of a structure. If the declaration is tagged, however, the tag can
be used later in definitions of instances of the structure. For example, given the declaration of
point above,
struct point pt;
defines a variable pt

which is a structure of type struct point. A structure can be initialized


by following its definition with a list of initializers, each a constant expression, for the
members:
struct maxpt = { 320, 200 };

An automatic structure may also be initialized by assignment or by calling a function that


returns a structure of the right type.
The only legal operations on a structure are copying it or assigning to it as a unit, taking its
address with &, and accessing its members. Copy and assignment include passing arguments to
functions and returning values from functions as well. Structures may not be compared. A
structure may be initialized by a list of constant member values; an automatic structure may
also be initialized by an assignment.
(*pp).x valid

pp->x also valid struct {int x; char p;} *pp;

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)

or NULL if the request cannot be satisfied.

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.

You might also like