“Modern C”: Notes on chapter 2 “The principal structure of a program”
By Dmitry Kabanov
These are my notes taken while reading chapter 2 “The principal structure of a program” from the book “Modern C” by Jens Gustedt. This chapter explains details of C grammar, distinction between declaration and definition of objects, and statements.
The table of contents for all notes for this book are available in that post.
2.1 Grammar
C program is a text consisting of different text elements:
- Special words (which are directives, keywords, and reserved), such as
#include
,int
,double
,return
,for
. - Brackets
{..}
,[..]
,(..)
to group parts of program together - Separators comma
,
(to separate arguments of a function. or elements of an array) and semicolon;
(to separate statements). - Comments
/*..*/
to comment parts of a program for readability. - Literals: numbers such as
1
,42
,0.007f
,3.14
,1.6e-28
,'A'
,"It's a string"
. - Identifiers: name of functions, macros, variables, or aliases for types.
- Operators: arithmetic
+
,-
,*
,/
, assignment=
, increment++
.
Takeaway 2.1. Punctuation can have several different meanings.
2.2 Declarations
Takeaway 2.2. All identifiers must be declared.
We can declare our own identifiers:
int myfunc(void); // Declare a function
double A[5]; // Array of five elements
size_t i; // Variable that represents lengths
Some identifiers are predeclared, for example, the function printf
,
type alias size_t
or constant EXIT_SUCCESS
.
We obtain these declarations by including corresponding header files
where we need them, for example, printf
comes from stdio.h
, while
EXIT_SUCCESS
comes from stdlib.h
, so we need to include these files
to our program:
#include <stdio.h>
#include <stdlib.h>
Header files are also called include files.
We can also read documentation for C in Unix-like operation systems in terminal:
man 3 printf
Section 3 of man
is devoted to the C programming language.
We can declare identifiers multiple times.
Takeaway 2.3. Identifiers may have several consistent declarations.
Takeaway 2.4. Declarations are bound to the scope in which they appear.
There is block scope, in which identifier is visible only in a given block, essentially, between a pair of curly braces:
int main(void) {
int age = 7; // Scoped to function
for (size_t i; i < age; ++i) { // Scoped to the for loop.
// Do stuff with i.
}
}
There is also file scope (or global scope), for example, function main
in every C program is in the global scope.
2.3 Definitions
Definitions define (ha-ha) concrete instances of declared identifiers.
For variables, declaration and definition can be combined in initialization:
size_t i = 42;
double A[3] = {
[0] = 2.72,
[1] = 3.14,
}; // Note that element [2] is initialized to zero.
Initialization of array with explicit indices is called designated.
Takeaway 2.7. Missing element in initializers default to 0.
Takeaway 2.8. For an array with \(n\) elements, the first element has index 0, and the last has index \(n - 1\).
A function is defined inside the pair of braces {..}
:
int main(void) {
...
}
Takeaway 2.9. Each object or function must have exactly one definition.
2.4 Statements
Statements are program steps that do something useful with the identifiers, for example, use defined variables and functions to compute an answer.
Iteration statement can be done with a for
statement:
for (initialization; condition; things to do after initialization) {
for-loop body
}
Takeaway 2.10. Domain iterations should be coded with a for
statement.
In old versions of C, all identifiers must be declared in the beginning of a function. Nowadays, it is not so, and it is recommended to declare an iteration variable directly in initialization:
for (int i = 0; i < 42; ++i) {
}
Takeaway 2.11. The loop variable should be defined in the initial part
of a for
loop.
Function calls are another type of statement in C programs:
printf("Hello World!\n");
Also important are return
statements that take the control
from a given point in a function and return it to the calling
function:
int add(int a, int b) {
int sum = a + b;
return sum; // Control goes back to the `main` function.
}
int main(void) {
int sum = add(2, 3);
return 0; // main must return 0 to indicate success.
}