A comment is a sequence of characters which explains a piece of code. Programmers use comments to say in plain English what the C commands in a program do. A comment begins with a /* and ends with a */.
Comments are ignored by the compiler - they exist solely to please humans reading the code. Every source file you write should start with a comment to explain what it does. It is often helpful to include your name and date as well. There should be lots of comments throughout the program to explain what is happening.
The examples below are taken from the source code of the minefield application.
Identifiers are user-supplied names for variables, functions and labels.
An identifier is a sequence of one or more letters, digits or underscores '_'. The name of a variable can then be used in place of its value. Similarly, the identifier of a function is used in place of the function. Some examples are given below.
| x | /* A variable named x */ |
| voltage | /* An informative variable name */ |
| Current | /* Upper- and lower-case letters are allowed in identifiers */ |
| sqrt( ) | /* A mathematical function */ |
There are some important restrictions upon the form an identifier can take:
- -Wid-clash-len
- Warn whenever two distinct identifiers match in the first len characters. This may help you prepare a program that will compile with certain obsolete, brain-damaged compilers.
| 90_entry | /* Identifiers may not start with a digit */ |
| -letter | /* Neither may they start with an operator */ |
| int | /* A reserved word can't be used as in identifier */ |
A constant is a fixed-value integer, real number character or string. It is an error to attempt to assign a value to a constant once it has been declared.
There are four types of constant in C:
const int x = 42; const double e = 2.7182818285; const char c = 'a'; const char s[] = "Hello, world!";
Note that 17 is an integer constant whereas 17.0 is a floating-point one. This can be confusing: 3/2 evaluates to 1 in C, because dividing an integer by an integer produces an integer result. 3.0/2.0 evaluates to 1.5. It is always best to express floating-point values that happen to be whole numbers with the trailing ".0" to avoid confusion.
The Alpha-numeric part of the C character set comprises upper and lower case letters, A-Z and a-z, and digits 0-9. The Alpha-numeric characters are used to form constants, identifiers and keywords. C is case-sensitive, so the identifier number is not the same as Number. Other characters are grouped together as white space (blank spaces, new lines and tabs characters); punctuation: (parentheses ( ), braces { }, commas ',' and semicolons ';' etc.); and special characters (e.g. +, -, *, /, !, &, ->, # etc.).
Special characters are mostly operators, and # is used by the pre-processor.
Control Sequences such as C-c are used to force things to happen at run-time. The sequence names are largely historical. Strictly, the association of the characters (like C-z) with an action (like suspend) are a function of the operating system rather than the C programming language, but the Unix control sequences are now almost uniformly adopted.
C uses Escape Sequences to represent non-printing characters. The solidus ("backslash") chacter is used as the escape. For example, '\a' is the "alert" of "Bell" chacter, C-g or BEL in ASCII. Esacape sequences can be used in strings and character constants.
| Sequence | Name | Code | Hex |
|---|---|---|---|
| \a | Bell (alert) | BEL | \0x07 |
| \b | Backspace | BS | \0x08 |
| \f | Form feed | FF | \0x0C |
| \n | New line | LF | \0x0A |
| \r | Carriage return | CR | \0x0D |
| \t | Horizontal tab | HT | \0x09 |
| \v | Vertical tab | VT | \0x0B |
| \0 | Null terminator | NUL | \0x00 |
| \\ | Back slash | \0x5C | |
| \' | Single quotation mark | \0x27 | |
| \" | Double quotation mark | \0x22 | |
| \ddd | ASCII character in octal | ||
| \xddd | ASCII character in hex |
An expression consists of an operator and its operand and it can occur whenever a value is allowed. In its simplest form an expression may be just a constant or a variable. Expressions can be combined with operators to create new expressions. As you can see from the examples, an expression can contain arithmetic or bitwise operators, returning a numberical result, or boolean (or logical) operators which compare values yielding a logical result.
An expression becomes a statement when it is used for a purpose. The examples above are turned into statements below. A statement in C is terminated by a semicolon. (Often when a program doesn't compile, it is a simple mistake like omitting a semicolon which is the cause of the error.)
A statement which explicitly modifies the value of a variable (e.g. i = 3) is called and assignment. C permits a very useful shorthand called an assignment operator which avoids stating the operand more than once:
Finally, statements can be grouped together into a block or compound statement by {enclosing them in braces}. At the moment, it won't be obvious why one should want to do this, but it is essential to allow such grouping when using conditional or loop constructs, which will be covered later.

Operators are special character combinations that specify how values are to be transformed and assigned. Operators perform specific transformations on operands. Some are more important than others - they have higher precedence. They are included below for completeness but it is not usually necessary to remember them. The golden rule here is to make the code clear so use lots of brackets; even use brackets where you don't need them if it increases readability. The code produced by the compiler won't be any larger slower because of extra brackets in the source.
| Precedence | Operator | Name | Notes |
|---|---|---|---|
| 1 | ( ) | Function or Parenthesis | |
| [] | Array | ||
| . | Member selection | ||
| -> | Member selection | ||
| 2 | + | Unary positive | RIGHT to LEFT |
| - | Unary negate | RIGHT to LEFT | |
| ~ | Bitwise one's complement NOT | ||
| ! | Logical NOT | ||
| * | Indirection | ||
| & | Reference ("Address of") | ||
| ++ | Increment | ||
| -- | Decrement | ||
| sizeof | Size in bytes | ||
| (type) | Type cast | ||
| 3 | * | Multiplication | |
| / | Division | ||
| % | Remainder | ||
| 4 | + | Addition | |
| - | Subtraction | ||
| 5 | << | Bitwise left shift | |
| >> | Bitwise right shift | ||
| 6 | < | Less than | |
| > | Greater than | ||
| <= | Less than or equal to | ||
| >= | Greater than or equal to | ||
| 7 | == | Equality | |
| != | Inequality | ||
| 8 | & | Bitwise AND | |
| 9 | ^ | Bitwise exclusive OR | |
| 10 | | | Bitwise inclusive OR | |
| 11 | && | Logical AND | |
| 12 | || | Logical OR | |
| 13 | exp1?exp2:exp3 | Conditional | RIGHT to LEFT |
| 14 | = | Simple assignment | RIGHT to LEFT |
| += | Addition assignment | ||
| -= | Subtraction assignment | ||
| *= | Multiplication assignment | ||
| /= | Division assignment | ||
| %= | Remainder assignment | ||
| >>= | Right shift assignment | ||
| <<= | Left shift assignment | ||
| &= | Bitwise AND assignment | ||
| |= | Bitwise OR assignment | ||
| ^= | Bitwise exclusive OR assignment | ||
| 15 | , | Sequential evaluation |
Keywords are reserved identifiers known to the compiler. Some of them, such as int and float have been introduced already. Others are described in future topics.
Because it would lead to multiple definitions, keywords cannot be used as user-defined identifiers.
The following is a list of keywords used by the compiler:
| auto | double | int | struct |
| break | else | long | switch |
| case | enum | register | typedef |
| char | extern | return | union |
| const | float | short | unsigned |
| continue | for | signed | void |
| default | goto | sizeof | while |
| do | if | static | volatile |
The pre-processor is the first stage of the compiler. The pre-processor directives tells the pre-processor what code to change before the compiler does its job. It could be used to define certain constants or include prototypes of standard functions.
Pre-processor directives all begin with a # character. It is important to appreciate that they are not part of the C language and different rules apply to their use. The most important is that, unlike C programs which can be laid out in any way which promotes readability, the # character must be the first character on the line although the # and the pre-processor directive may be separated on the line by white space.
The #define directive will substitute a given string for a different one everywhere it appears in the source code.
#define macros can be made to take arguments, just like a function, but it is important to bear in mind that all that is taking place is string substitution. It is crucial to make sure there are no side effects of expanding the macro: it might be defined inside a header file, and introduce some subtle programming errors.
The following example includes a file called stdio.h which contains numerous definitions and declarations used by the standard input/output library functions.
Quotation marks direct the compiler to begin the search in the current directory, then to proceed to any directory specified in the command line and finally (if still not found), to search in the standard directories.
This simplifies maintenance when repeated across several source code files as only one directive or definition has to be changed for it to effect all by inclusion all subsequent compilations. Files of this nature are termed header files and by convention have the filename extension .h.

It is good practice to include the associated .h file in the .c file. The reason for this is that very subtle bugs can be introduced if the programmer makes changes to the functions in the .c file, and inadvertently forgets to modify the .h file. Other .c files are now mis-informed as to the contents of the compiled object file. By including the .h file in the .c file, the compiler will check that both agree, and cause an error to be thrown if there is a mismatch.


A solution is to use the conditional preprocessor directives #ifndef, #ifdef and so on. Consider the following example:
Note that the choice of preprocessor symbol, __MYHEADER_H__, is entirely arbitrary, but you should keep it consistent across all of the .h files in the package. In the section on identifiers, we warned against starting an identifier with an _ character. This does not apply to preprocessor symbols, which are not C program identifiers: when the file is fully expanded, the compiler will not read any of the preprocessor strings.
Step through the following noticing the comment associated with each line. Try entering the code, compiling it and running it as explained in the tools section. Remember not to enter the line numbers!
Summary:
C programs consist of various different constructs, including comments, identifiers, constants, statements and expressions, operators and keywords.
Before the compiler translates C to machine code, the source is passed through a pre-processor which permits macro definitions and the inclusion of other files.
The tools upon which this course relies are Copyright the Free Software Foundataion where they are made available under the GPL (GNU Public Licence).
The content of this course was derived from that generated by many ex-colleagues at the University of Leeds, Department of Electronics and Electrical Engineering. Much of the content has been reworked, and substantially augmented, but Dr N J Bailey, Centre for Music Technology, The University of Glagsow. This manifestation is Copyright N J Bailey; some of the content is Copyright The University of Leeds.
Diagrams on this resource are drawn in XFig and are rendered by the browser using The University of Hamburg's Simple FIG viewer applet which is Copyright (C) 1996-2002 F.N.Hendrich, hendrich@informatik.uni-hamburg.de.
The source code, programming examples and exercises are all specific to this course, and are Copyright, Dr N J Bailey.
The applet for viewing and demonstrating C programs is Copyright Dr N J Bailey, and is to be found documented and with its source code on the Centre for Music Technology website under Software