C allows for commands to the compiler to be included in the
source code. These commands are then called preprocessor commands and are
defined by the ANSI standard to be;
#if
#ifdef
| #ifndef
| #else
| #elif
| #include
| #define
| #undef
| #line
| #error
| #pragma | |
All preprocessor commands start with a hash symbol,
"#", and must be on a line on their own (although comments may
follow).
The #define command specifies an identifier and a string that
the compiler will substitute every time it comes accross the identifier within
that source code module. For example;
#define FALSE 0
#define TRUE !FALSE
The compiler will replace any subsequent occurence of 'FALSE'
with '0' and any subsequent occurence of 'TRUE' with '!0'. The substitution does
NOT take place if the compiler finds that the identifier is enclosed by
quotation marks, so
printf
("TRUE");
would NOT be replaced, but
printf
("%d",FALSE);
would be.
The #define command also can be used to define macros that may
include parameters. The parameters are best enclosed in parenthesis to ensure
that correct substitution occurs.
This example declares a macro 'larger()' that accepts two parameters and returns the larger of the two;
#include <stdio.h>
#define larger(a,b) (a > b) ? (a) : (b)
int main()
{
printf
("\n%d is largest",larger(5,7));
}
The #error command causes the compiler to stop compilation and
to display the text following the #error command. For example;
#error REACHED MODULE B
will cause the compiler to stop compilation and display;
REACHED MODULE B
The #include command tells the compiler to read the contents
of another source file. The name of the source file must be enclosed either by
quotes or by angular brackets thus;
#include "module2.c"
#include <stdio.h>
Generally, if the file name is enclosed in angular brackets,
then the compiler will search for the file in a directory defined in the
compiler's setup. Whereas if the file name is enclosed in quotes then the
compiler will look for the file in the current directory.
The #if set of commands provide conditional compilation around
the general form;
#if constant_expression
statements
#else
statements
#endif
#elif stands for '#else if' and follows the form;
#if expression
statements
#elif expression
statements
#endif
These two commands stand for '#if defined' and '#if not
defined' respectively and follow the general form;
#ifdef macro_name
statements
#else
statements
#endif
#ifndef macro_name
statements
#else
statements
#endif
where 'macro_name' is an identifier declared by a #define
statement.
Undefines a macro previously defined by #define.
Changes the compiler declared global variables __LINE__ and
__FILE
__. The general form of #line is;
#line number "filename"
where number is inserted into the variable '__LINE__' and
'filename' is assigned to '__FILE
__'.
This command is used to give compiler specific commands to the compiler. The compiler's manual should give you full details of any valid options to go with the particular implementation of #pragma that it supports.
As with any computer language, C includes statements that test
the outcome of an expression. The outcome of the test is either TRUE or FALSE.
The C language defines a value of TRUE as non-zero, and FALSE as zero.
The general purpose selection statement is "if" that
follows the general form;
if (expression)
statement
else
statement
Where "statement" may be a single statement, or a
code block enclosed in curly braces. The "else" is optional. If the
result of the expression equates to TRUE, then the statement(s) following the
if() will be evaluated. Otherwise the statement(s) following the else, if there
is one, will be evaluated.
An alternative to the if....else combination is the ?: command
that takes the form;
expression ? true_expression : false_expression
Where if the expression evaluates to TRUE, then the
true_expression will be evaluated, otherwise the false_expression will be
evaluated. Thus we get;
#include <stdio.h>
main()
{
int x;
x = 6;
printf ("\nx is an %s number", x % 2 == 0 ? "even" : "odd");
}
C also provides a multiple branch selection statement, switch
, which successively tests a value of an expression against a list of values and
branches program execution to the first match found. The general form of switch
is;
switch (expression)
{
case value1 : statements
break ;
case value2 : statements
break ;
.
.
.
.
case valuen : statements
break ;
default : statements
}
The break
statement is optional, but if omitted, program execution will continue
down the list.
#include <stdio.h>
main()
{
int x;
x = 6;
switch (x)
{
case 0 : printf ("\nx equals zero");
break ;
case 1 : printf ("\nx equals one");
break ;
case 2 : printf ("\nx equals two");
break ;
case 3 : printf ("\nx equals three");
break ;
default : printf ("\nx is larger than three");
}
}
Switch statements may be nested within one another. This is a
particularly useful feature for confusing people who read your source code!
C provides three looping or iteration statements; for, while,
and do-while. The for loop has the general form;
for(initialization;condition;increment)
and is useful for counters such as in this example that
displays the entire ascii character set;
#include <stdio.h>
main()
{
int x;
for(x = 32; x < 128; x++)
printf ("%d\t%c\t",x,x);
}
An infinite for loop is also quite valid;
for(;;)
{
statements
}
Also, C allows empty statements. The following for loop
removes leading spaces from a string;
for(; *str == ' '; str++)
;
Notice the lack of an initializer, and the empty statement
following the loop.
The while loop is somewhat simpler than the for loop and
follows the general form;
while (condition)
statements
The statement following the condition, or statements enclosed
in curly braces will be executed until the condition is FALSE. If the condition
is false before the loop commences, the loop statements will not be executed.
The do-while loop on the other hand is always executed at least once. It takes
the general form;
do
{
statements
}
while(condition);
The "return" statement is used to return from a
function to the calling function. Depending upon the declared return data type
of the function it may or may not return a value;
int MULT(int x, int y)
{
return(x * y);
}
or;
void FUNCA()
{
printf ("\nHello World");
return;
}
The "break
" statement is used to break out of a loop or from a switch
statement. In a loop it may be used to terminate the loop prematurely, as shown
here;
#include <stdio.h>
main()
{
int x;
for(x = 0; x < 256; x++)
{
if (x == 100)
break
;
printf ("%d\t",x);
}
}
In contrast to "break
" is "continue
", which forces the next iteration of the loop to occur, effectively
forcing program control back to the loop statement.
C provides a function for terminating the program prematurely,
"exit()". Exit() may be used with a return value to pass back to the
calling program;
exit(return_value);
A powerful, but often misunderstood feature of the C
programming language is ?:. This is an operator that acts upon a boolean
expression, and returns one of two values dependant upon the result of the
expression;
<boolean expression> ? <value for true> :
<value for false>
It can be used almost anywhere, for example it was used in the
binary search demonstration program;
printf
("\n%s\n",(result == 0) ? "Not found" : "Located
okay");
Here it passes either "Not found" or "Located okay" to the printf () function dependant upon the outcome of the boolean expression 'result == 0'. Alternatively it can be used for assigning values to a variable;
x = (a == 0) ? (b) : (c);
Which will assign the value of b to variable x if a is equal
to zero, otherwise it will assign the value of c to variable x.
This example returns the name of the executing program,
without any path description;
#include <stdio.h>
#include <stddef.h>
#include <string.h>
char *progname(char *pathname)
{
/* Return name of running program */
unsigned l;
char *p;
char *q;
static char bnbuf[256];
return pathname? p = strrchr (pathname, '\\'),
q = strrchr (pathname, '.'),
l = (q == NULL? strchr (pathname, '\0'): q)
- (p == NULL? p = pathname: ++p),
strncpy (bnbuf, p, l),
bnbuf[l] = '\0',
strlwr (bnbuf)
: NULL;
}
void main(int argc, char *argv[])
{
printf ("\n%s",progname(argv[0]));
}
The continue
keyword forces control to jump to the test statement of the innermost loop
(while, do...while()). This can be useful for terminating a loop gracefuly as
this program that reads strings from a file until there are no more illustrates;
#include <stdio.h>
void main()
{
FILE *fp;
char *p;
char buff[100];
fp = fopen("data.txt","r");
if (fp == NULL)
{
fprintf(stderr ,"Unable to open file data.txt");
exit(0);
}
do
{
p = fgets(buff,100,fp);
if (p == NULL)
/* Force exit from loop */
continue ;
puts(p);
}
while(p);
}
With a for() loop however, continue passes control back to the third parameter!
Links: Home C Programming Guide C++ programming Guide