In the absence of explicit initialization, external and static variables are guaranteed to be initialized to zero; automatic and register variables have undefined (i.e., garbage) initial values.
Scalar variables may be initialized when they are defined, by following the name with an equals sign and an expression:
int x = 1; char squota = '\''; long day = 1000L * 60L * 60L * 24L; /* milliseconds/day */
For external and static variables, the initializer must be a constant expression; the initialization is done once, conceptionally before the program begins execution.
For automatic and register variables, the initializer is not restricted to being a constant: it may be any expression involving previously defined values, even function calls.
int binsearch(int x, int v[], int n) { int low = 0; int high = n - 1; int mid; ... }
An array may be initialized by following its declaration with a list of initializers enclosed in braces and separated by commas. For example, to initialize an array days with the number of days in each month:
int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
When the size of the array is omitted, the compiler will compute the length by counting the initializers, of which there are 12 in this case.
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";
Above is a shorthand for the longer but equivalent char pattern[] = { 'o', 'u', 'l', 'd', '\0' }; In this case, the array size is five (four characters plus the terminating '\0').
C functions may be used recursively; that is, a function may call itself either directly or indirectly.
When a function calls itself recursively, each invocation gets a fresh set of all the automatic variables, independent of the previous set.
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.
Q. Demonstrate Recursion for program of Quicksort
/* qsort: sort v[left]...v[right] into increasing order */ void qsort(int v[], int left, int right) { int i, last; void swap(int v[], int i, int j); if (left >= right) /* do nothing if array contains */ return; /* fewer than two elements */ swap(v, left, (left + right)/2); /* move partition elem */ last = left; /* to v[0] */ for (i = left + 1; i <= right; i++) /* partition */ if (v[i] < v[left]) swap(v, ++last, i); swap(v, left, last); /* restore partition elem */ qsort(v, left, last-1); qsort(v, last+1, right); }
/* swap: interchange v[i] and v[j] */ void swap(int v[], int i, int j) { int temp; temp = v[i]; v[i] = v[j]; v[j] = temp; }
A definition has the form #define name replacement text. It calls for a macro substitution of the simplest kind - subsequent occurrences of the token name will be replaced by the replacement text.
It is also possible to define macros with arguments, so the replacement text can be different for different calls of the macro.
#define max(A, B) ((A) > (B) ? (A) : (B))
Although it looks like a function call, a use of max expands into in-line code. Each occurrence of a formal parameter (here A or B) will be replaced by the corresponding actual argument. Thus the line x = max(p+q, r+s); will be replaced by the line x = ((p+q) > (r+s) ? (p+q) : (r+s));
So long as the arguments are treated consistently, this macro will serve for any data type; there is no need for different kinds of max for different data types, as there would be with functions.
Names may be undefined with #undef, usually to ensure that a routine is really a function, not a macro:
#undef getchar int getchar(void) { ... }
The #if line evaluates a constant integer expression (which may not include sizeof, casts, or enum constants). If the expression is non-zero, subsequent lines until an #endif or #elif or #else are included.
#if SYSTEM == SYSV #define HDR "sysv.h" #elif SYSTEM == BSD #define HDR "bsd.h" #elif SYSTEM == MSDOS #define HDR "msdos.h" #else #define HDR "default.h" #endif #include HDR
This sequence tests the name SYSTEM to decide which version of a header to include.