An array is defined by writing the data type followed by the name followed by the size in
brackets; for example,
int x[20];
double car[ROWS][COLS];
In the first case, the variables x[0], x[1], ... ,x[19]
are
created. In the second case, a 2-D array (matrix) is created. In C, array
names without the brackets are pointers.
When the statement
break;
is encountered, the innermost while, do while, for, or switch construct is terminated.
The cast operator is written as
(type)
where type
is a data type. When the cast operator is executed, the operand is converted to type
. As examples, if we write:
int i = 2;
float x;
x = (float) i;
the value of i is converted to float and copied into x. If we write:
struct node {
char* data;
struct node* link;
};
struct node* ptr;
ptr = malloc(sizeof (struct node));
storage for one structure whose members are data and link is allocated by the library function malloc. The address of this storage is assigned to ptr.
A C comment is delimited by /*
and */
.
Integer constants may be written in decimal:
130 45 88203
An integer constant that begins with 0 (zero) is an octal number:
0130 045
A sequence of digits preceded by 0X or 0x is a hexadecimal number:
0x90A 0Xf2
Either lowercase a through f or uppercase A through F is acceptable.
An integer constant may be terminated by u or U, to indicate that it is unsigned, or by l or L to indicate that it is long. If a decimal constant is not terminated with either u, U, l, or L, it is the first of the types int, long, or unsigned long in which its value can be represented. If an octal or hexadecimal constant is not terminated with either u, U, l, or L, it is the first of the types int, unsigned int, long, or unsigned long in which its value can be represented. If a decimal, octal, or hexadecimal constant is terminated with either u or U, it is the first of the types unsigned int or unsigned long in which its value can be represented. If a decimal, octal, or hexadecimal constant is terminated with either l or L, it is the first of the types long or unsigned long in which its value can be represented. If a decimal, octal, or hexadecimal constant is terminated with either l or L and u or U, it is of type unsigned long.
A floating-point constant consists of a string of digits (integral part) followed by a
decimal point followed by a string of digits (fractional part) followed by an integer
exponent. The integer exponent is e or E optionally followed by + or followed by a
string of digits. Either the integral part or the fractional part, but not both, may be
omitted. Either the decimal point or the integer exponent, but not both, may be omitted.
Examples of floating-point constants are:
2.0 4.3e4 9.21E9 13.E+4 4e3 .390
A floating-point constant may be terminated by f or F to indicate that it is a float or by l or L to indicate that it is a long double. If a floating-point constant is not terminated with either f, F, l, or L, it is of type double.
A char constant is delimited by single quotation marks, for example, 'Y'
.
A string constant is delimited by double quotation marks, for example,
"This is a string constant."
C recognizes the following escape sequences in character and string constants:
Constant | Meaning |
\a | Ring bell (alert) |
\b | Backspace |
\f | Formfeed |
\n | Newline |
\r | Carriage return |
\t | Horizontal tab |
\v | Vertical tab |
\\ | Backslash |
\' | Single quote |
\" | Double quote |
\? | Question mark |
\ddd | Octal constant |
\xhh | Hexadecimal constant |
Return to Table of Contents
Continue
When the statement
continue;
is encountered in a while or do while loop, control passes to the condition that determines whether to execute the body of the loop again. When the statement
continue;
is encountered in a for loop, control passes to the update statement, expr3, in
for (expr1; expr2; expr3) body
Then expr2 is evaluated to determine whether to execute body again.
The integer data types are char
, short int
(which may be abbreviated short
), int
, and long int
(which may be abbreviated long
). The sizes of these data types satisfy
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
The signed integer types are signed char
, signed short int
,
signed int
, and signed long int
. In addition, the unsigned integer types
unsigned char
, unsigned short int
, unsigned int
(which may be abbreviated unsigned
), and unsigned long int
are available.
The floating-point data types are float
, double
, and long double
. The sizes of these data types satisfy
sizeof(float) <= sizeof(double) <= sizeof(long double)
Some other types, defined in standard headers, are given in the following table:
Type | Defined in | Represents |
---|---|---|
ptrdiff_t | stddef.h | The difference of two pointers |
size_t | stddef.h stdio.h stdlib.h string.h time.h |
The value of sizeof |
va_list | stdarg.h | Information needed by macros in stdarg.h |
FILE | stdio.h | Information needed to manipulate files |
fpos_t | stdio.h | A position within a file |
clock_t | time.h | Time |
time_t | time.h | Time |
See also enum.
Return to Table of Contents
Define
The #define statement is often used to create symbolic (also called manifest) constants. For example, the statement
#define WIDTH 80 /* Characters per line */
Notice there is no equals sign in the definition and it is not followed by a semicolon.
Return to Table of Contents
Do While
The statement
do body while (condition) ;
results in the execution of body
as long as condition
is true (nonzero). The condition
is tested after body is executed. In addition, body
must be enclosed in braces unless it consists of a single statement, in which case it is simply terminated with a semicolon.
Return to Table of Contents
Enum
An enumerated type is a data type with user-specified values. For example, the
declaration
enum director (Hitchcock, Huston, Meyer);
describes the enumerated type enum director. A variable of type enum director should take
one of the values Hitchcock, Huston, or Mayer. To define a variable name of type enum director, write
enum director name;
After the preceding definition, the assignment
name = Huston;
is valid.
Return to Table of Contents
For
The statement
for (expr1; expr2; expr3) body
first executes expr1
. Then, as long as expr2
is true (i.e., nonzero), body
is executed followed by expr3
. Note that expr2
is tested before body and expr3
are executed. In addition, body
must be enclosed in braces unless it consists of a single statement, in which case it is simply terminated with a semicolon.
Return to Table of Contents
Functions
The definition of a function consists of a header and a body. The header consists of the
data type returned followed by the function's name followed by the data types and names
of any parameters (also called arguments) in parentheses. If the function returns no value, the keyword void occurs in place of the returned data type. If there are no parameters, the keyword void
occurs in parentheses. No semicolon follows the right parenthesis. The body of the
function, that is, the code that implements the function, follows the header and is enclosed
in braces.
A declaration of a function resembles a function header. The declaration consists of the data type returned followed by the function's name, followed, in parentheses, by the data types and optional names of the expected arguments terminated by a semicolon. If the function returns no value, the keyword void occurs in place of the returned data type. If there are no expected arguments, the keyword void occurs in the parentheses.
Here is an example of a function definition:
int fun(char letter) /* header */
{
/* body */
}
Here is a declaration of the preceding function:
int fun( char letter);
In C, function parameters are normally passed by value. That is, the value of each parameter is copied to a local variable when the function is called. This local variable is distroyed when the function returns. Any changes made to the local copy of a parameter are lost upon return as a result of this mechanism.
Pointers can be used to pass variables to functions such that their values can be changed in the functions and their modified values returned. For example, the function
void swap(float* x, float* y)
{
float z;
z = *x;
*x = *y;
*y = z;
return;
}
could be called as follows
swap(&a, &b);
to interchange the values of float variables a and b. Notice the use of the address-of operator (&) in calling statement and the indirection operator (*) in the function body.
Return to Table of Contents
If
The expression
if (condition) body
Results in the execution of body if condition is true (nonzero). Otherwise, control skips to the statement immediately following body. In addition, body must be enclosed in braces unless it consists of a single statement, in which case it is simply terminated with a semicolon.
The expression
if (condition) body1 else body2
Results in the execution of body1 if condition is true (nonzero). Otherwise, body2 is executed. In either case, the next statement executed is the statement immediately following body2. In addition, body1 must be enclosed in braces unless it consists of a single statement, in which case it is simply terminated with a semicolon. Similarly, body2 must be enclosed in braces unless it consists of a single statement, in which case it is simply terminated with a semicolon.
Return to Table of Contents
Initializing in Definitions
Any variable may be initialized in its definition be writing, for example,
int x = 5;
An array can be initialized, for example, by writing
int age[ 5 ] = { 4, 32, 5, 27, 29 };
A structure can be initialized, for example, by writing
struct data {
int day;
char* month;
int year;
} due_date = { 8, "Jan", 1990 };
The C keywords are listed below. These words should not be used as identifiers (variable names).
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
Return to Table of Contents
Pointers
A pointer must be defined so as to point to a particular data type. For example, in the case of
int* ptr;
ptr can hold the address of an int.
The syntax
*ptr
assesses the contents of the cell whose address is ptr. The star (*) is called the indirection operator. The address-of operator (&) is used to obtain the address of a variable. For example
results in variable a and pointer b refering to the same memory location.
int a
int* b
b = &a
Return to Table of Contents
Operators and Precedence
The C operators are list from highest (evaluated first) to lowest (evaluated last) precedence in the following table. Operators between horizontal lines have the same precedence.
Description | Operator(s) | Associates from the |
---|---|---|
Function expression |
( ) |
left |
Increment/decrement |
++ -- |
right |
Multiplication |
* |
left |
Addition |
+ |
left |
Shift left |
<< |
left |
Less than |
< |
left |
Equal |
== |
left |
Bitwise and |
& |
left |
Bitwise exclusive or |
^ |
left |
Bitwise inclusive or |
| |
left |
Logical and |
&& |
left |
Logical or |
|| |
left |
Conditional |
? : |
right |
Assignment |
= %= += -= *= /=
|
right |
Comma |
, |
left |
Return to Table of Contents
Return
When the statement
return;
is encountered, the function returns to its invoker without returning a value.
When the statement
return expression;
is encountered, the function returns to its invoker the value of expression.
The statement return expression;
has the same meaning as return(expression);
.
Return to Table of Contents
Sizeof
The value of the sizeof operator is the size, in bytes, of its operand. One byte is
defined to be sizeof (char). If a is an array, sizeof (a)
is the total size,
in bytes, of a. If a is a structure, sizeof (a)
is the total size, in bytes, of all of the members of a. Because sizeof is an operator and not a function, its value is known at compile time. For this reason, it is legal to write
struct date {
int day;
char* month;
int year;
};
#define DATE_SIZE sizeof (struct date)
Return to Table of Contents
Standard Headers
The following table lists the header files mandated by the ANSI C Standard and gives a brief
description of the purpose of each.
Header File | Purpose |
assert.h | Putting diagnostics into programs |
ctype.h | Testing and modifying characters |
errno.h | Reporting error conditions |
float.h | Describing floating-point types |
limits.h | Describing integer types |
locale.h | Formatting numeric values |
math.h | Mathematical functions |
setjmp.h | Bypassing default function call and return conventions |
signal.h | Handling signals |
stdarg.h | Writing functions with an arbitrary number of arguments |
stddef.h | Common definitions |
stdio.h | Handling input and output |
stdlib.h | General utilities |
string.h | Handling arrays of characters |
time.h | Handling time |
Return to Table of Contents
Storage Classes
The C storage classes are
auto extern static register
Return to Table of Contents
Structures
A structure declaration consists of struct followed by an optional structure tag
followed by the declaration of its members in braces. The terminating brace must be
followed by a semicolon. For example;
struct data {
int day;
char* month;
int year;
};
Given a structure declaration one can define a structure of the given type by
writing struct followed by the structure tag followed by the name of the variable to be
defined. For example, given the preceding structure declaration, we can define a structure d by writing
struct date d;
It is possible to declare and define structures simultaneously.
A member of a structure can be accessed by using the dot operator. For example, given the preceding declaration and definition, we may access month in d by writing
d.month
The syntax (*s).x
is equivalent to s->x
.
C permits structure assignments using the assignment operator =
and permits
passing structures to functions and returning structures from functions.
Return to Table of Contents
Switch
The switch statement has the form
switch (expression) {
case c1:
statements1
case c2:
statements2
...
default:
default statements
}
When the construct is executed, expression is evaluated. Control passes to the line at
which expression is equal to ci. (Each of c1, c2, ... must be distinct.) If expression is not equal to any of the ci's, control passes to default statements. Execution continues until a break statement is encountered, at which point control passes to the first statement after default statements. If no break
statement is present, execution continues through all the statements, beginning with the first case in which ci equals expression. Normally, each of statements1, statements2, ..., default statements concludes with a break;
statement.
Each of c1, c2, ... must be an integer constant and the default block is optional.
Return to Table of Contents
Typedef
The use of typedef creates a synonym for some other data type. For example, if we write
the types struct x and DATE are synonyms. Given the preceding typedef, writing
typedef struct x {
int day;
char* month;
int year;
} DATE;
DATE d;
is the same as writing
struct x {
int day;
char* month;
int year;
} d;
Return to Table of Contents
Type Qualifiers
Type qualifiers are specified by the keywords const
and volatile
and are used to inform the compiler about the behavior of variables and parameters. The type qualifier
const
("constant") indicates to the compiler that a variable or parameter is not to have
its value reset. Any attempt to reset the value of a const
variable or parameter results in
an error. The type qualifier volatile
indicates to the compiler that a variable or
parameter may have its value set by something (e.g., an operating system call) outside the
C program. In effect, the volatile
type qualifier warns an optimizing compiler against
making assumptions about how the value of the variable or parameter will be set.
The type qualifiers may occur together in variable definitions and parameter declarations. However, the type qualifiers always come after the storage class and before the data type. Here are two examples:
const int num = 10; /* variable definition */
void fun(const float real) /* parameter declaration */
Return to Table of Contents
Union
The union construct is syntactically identical to the structure construct (see Structures). A union may, at different times, hold one, and only one, of the types defined. For example, if we define
union num {
int x;
float y;
} u;
u may hold an int or a float, but not both. Storage is allocated for the largest of the data types specified. A member of union u is accessed syntactically exactly as a member of a structure.
Return to Table of Contents
Void
The keyword void shows that a function returns no value or expects no arguments. For
example
void f(int x, int y)
is the header of a function with two parameters, both of type int, that returns no value.
As another example,
float g(void)
is the header of a function with no parameters that returns a value of type float. Also, certain library functions such as malloc return a pointer to void.
Return to Table of Contents
While
When we execute
while (condition) body
as long as condition is true (nonzero), we execute body. The condition is tested before body is executed. In addition, body is enclosed in braces unless it consists of a single statement, in which case it is simply terminated with a semicolon.
Johnsonbaugh, R. and M. Kalin's "C for Scientists and Engineers," Prentice Hall, 1996.
Waite, M. and S. Prata's "The Waite Group's New C Primer Plus," Macmillan Computer Publishing, 1991.
Send comments and suggestions to: Charles S. Tritt, Ph.D.