The C language
Granet Vincent December 6, 2016
0-1
Table of contents
1 Bibliography . . . 1
2 Presentation . . . 3
3 Getting started . . . 8
4 Basic types . . . 18
5 Variable declarations . . . 31
6 Expression . . . 36
7 Statements . . . 45
8 The preprocessor (1) . . . 61
9 Functions . . . 68
10 Arrays . . . 84
11 Structures and Unions . . . 93
12 Pointers . . . 105
13 Input/Output . . . 125
14 Separate compilation . . . 136
15 The preprocessor (2) . . . 144
16 C library . . . 153
17 Programming environment . . . 157
Bibliography
Part 1: Bibliography
References
[1] American National Standard for Information Systems. Programming Language – C, ANSI X3.159-1989, 89.
[2] Brian W. Kernighan and Dennis M. Ritchie.
The C Programming Language. Prentice-Hall, second edition, 1988. (also published in
French, ed. MASSON).
[3] Samuel P. Harbison and Guy L. Steele. C: A Reference Manual. Prentice-Hall, second edition, 1987. (also published in French, ed.
MASSON).
[4] P. Drix. Langage C, norme ANSI. Masson, second edition, 1994. revue et augmente.
[5] J.P. Braquelaire. Mthodologie de la
programmation en langage C. Masson, 1995.
[6] FAQ C. see comp.lang.c and
http://www.eskimo.com/~scs/C-faq/top.html.
Presentation
Part 2: Presentation
History
❍ 1972 Dennis RITCHIE – Bell Laboratories Algol 60
BCPL (1967, M. Richard) B (1970, K. Thompson)
❍ System writing language
❍ Unix – Portability
❍ Traditional – K&R 1978 (obsolete)
❍ ANSI C: 1983 (X3J11) ⇒ 1989 (X3.159-1989)
⇒ ISO/IEC 9899:1990
Part 2: Presentation
Main features
❍ Procedural typed language – type constructors
❍ Separate compilation
❍ Archaic modularity model
❍ No input/output
❍ No dynamic allocation
❍ No concurrency
❍ C standard library
Part 2: Presentation
Evaluation: advantages
❍ Simplicity
❍ Efficiency
❍ Extensive library
❍ Good portability (PPC 1978, root of most public implementations)
❍ Also used as assembly language (C++, Eiffel, Modula 3, ...)
❍ Availability on most systems
Part 2: Presentation
Evaluation: drawbacks
❍ Two level syntax (preprocessor)
❍ Type checking is too permissive (but lint and ANSI C)
❍ Use of pointers can be tricky
❍ Programmer must be responsible
❍ Old language concepts
REFERENCES 7-1
¡
Getting started
Part 3: Getting started
My first C program
/* Write " Hello , world !" on s t a n d a r d output */
#i n c l u d e < stdio .h >
#i n c l u d e < stdlib .h >
i n t main (v o i d) {
printf (" Hello , world !\ n ");
r e t u r n E X I T _ S U C C E S S ; }
Compilation with Gnu C compiler:
$ gcc -ansi -Wall -o hello hello.c Execution:
$ hello
Hello world!
$
Part 3: Getting started
compiler cpp hello.c
hello gcc
gcc -ansi -Wall -o hello hello.c
Part 3: Getting started
Multi-file program
main.c
e x t e r n v o i d s a y _ h e l l o (v o i d);
i n t{} main (v o i d) {
s a y _ h e l l o ();
r e t u r n E X I T _ S U C C E S S ; }
hello.c
#i n c l u d e < stdio .h >
v o i d s a y _ h e l l o (v o i d) {
printf (" Hello , world !\ n ");
}
Part 3: Getting started
Compiling multi-file program
Compilation:
$ gcc -ansi -Wall -o hello main.c hello.c or
$ gcc -ansi -Wall -c hello.c
$ gcc -ansi -Wall -c main.c
$ gcc -o hello main.o hello.o Execution:
$ hello
Hello, world!
$
Part 3: Getting started
libc
gcc -o hello main.c hello.c
stdio.h
main.c
main.o cpp
compiler gcc
hello
cpp
compiler gcc
hello.o hello.c
ld (linker)
Part 3: Getting started
Simplified version of cat
/* Not in C style */
#i n c l u d e < stdio .h >
#i n c l u d e < stdlib .h >
i n t main (v o i d) {
i n t c ;
c = getchar ();
w h i l e ( c != EOF ) { putchar ( c );
c = getchar ();
}
r e t u r n E X I T _ S U C C E S S ; }
Part 3: Getting started
/* C style ; assignment is an expression ! */
#i n c l u d e < stdio .h >
#i n c l u d e < stdlib .h >
i n t main (v o i d) {
i n t c ;
w h i l e (( c = getchar ()) != EOF ) putchar ( c );
r e t u r n E X I T _ S U C C E S S ; }
Part 3: Getting started
Characters counting
#i n c l u d e < stdio .h >
#i n c l u d e < stdlib .h >
i n t main (v o i d) {
l o n g nbchar = 0 L ;
w h i l e ( getchar () != EOF ) nbchar ++;
printf (" I ’ ve read % ld c h a r a c t e r s \ n ", nbchar );
r e t u r n E X I T _ S U C C E S S ; }
Part 3: Getting started
#i n c l u d e < stdio .h >
#i n c l u d e < stdlib .h >
i n t main (v o i d) {
l o n g nbchar ;
f o r( nbchar = 0; getchar () != EOF ; nbchar + /* Nothing */;
printf (" I ’ ve read % ld c h a r a c t e r s \ n ", nbcha r e t u r n E X I T _ S U C C E S S ;
}
Basic types
Part 4: Basic types
C types
❍ void
❍ Scalar types
– Arithmetic types
∗ Integer types
∗ Real types
– Enumerated types – Pointer types
❍ Function types
❍ Structured types – Arrays
– Structures – Unions
Part 4: Basic types
void type
❍ No object can be of this type
❍ Used to define a function with no result (procedure)
❍ Also used with pointers
Part 4: Basic types
Integer types
❍ Signed integer or unsigned integer values
❍ Bit fields
❍ Boolean values (no boolean type in C!)
❍ Characters
Part 4: Basic types
Signed integers
❍ short [ int ]
❍ int
❍ long [ int ]
❍ long long [ int ]
❍ −2n−1..2n−1 −1, two’s complement
❍ −(2n−1 −1)..2n−1−1, one’s complement sizeof(short) 6 sizeof(int) 6 sizeof(long)
Examples:
123 (decimal) 0173 (octal) Ox7B (hexadecimal) 123L (long int)
Note: <limits.h> defines several minimums and maximums for arithmetic types. For example,
#define INT MIN -32767
Part 4: Basic types
Unsigned integers
❍ unsigned short [ int ]
❍ unsigned int
❍ unsigned long [ int ]
❍ unsigned long long [ int ]
❍ 0..2n −1
sizeof(unsigned short) 6 sizeof(unsigned) 6 sizeof(unsigned long)
❍ arithmetic is modulo 2n (i.e. max + 1 == 0)
❍ signed + unsigned = unsigned (K&R)
❍ signed + unsigned = signed (K&R)
Examples:
123 (decimal) 0173 (octal) Ox7b (hexadecimal) 123u (unsigned int) 123ul (unsigned long)
Part 4: Basic types
Characters
Character values can be used in integer expressions
❍ [ unsigned ] char
❍ character values are always positive
❍ representation depends on implementation (signed, unsigned, pseudo-unsigned)
u n s i g n e d c h a r c = 255;
i f ( c / -1 == 1) printf (" signed \ n ");
e l s e i f ( c / -1 == 0) /* K & R */
printf (" unsigned \ n ");
e l s e i f ( c / -1 == -255)
printf (" unsigned ( ansi ) or pseudo - unsign e l s e fprintf ( stderr ," weird \ n ");
❍ EOF problem
Examples:
Part 4: Basic types
’\a’ (audible bell)
’\b’ (backspace) ’\f’ (form feed)
’\n’ (newline) ’\r’ (carriage return)
’\t’ (horizontal tab) ’\v’ (vertical tab)
Part 4: Basic types
Reals
❍ float
❍ double
❍ long double
sizeof(float) 6 sizeof(double) 6sizeof(long double)
Examples:
0. .0 2.123 3e1 1.3E-12 2e+23 12.34f 0e-34F 0.0L 98.e-4l
Part 4: Basic types
Internal representations
❍ Sizes of simple types are not specified by the language (they depend on the machine)
❍ By definition sizeof(char) == 1
sizeof(char) 6 sizeof(short) 6 sizeof(int) 6sizeof(long)
8,16,32,32 Sparc Sun (32 bits) 8,16,32,64 PC (64 bits)
sizeof(float) 6 sizeof(double) 6 sizeof(long double)
32,64,64 DEC Alpha (32 bits) 32,64,128 PC (64 bits)
Part 4: Basic types
Enumerated types (1/2)
Similar to Pascal enumerated types
enum color { green , red , blue };
Identifiers represent integer constants, and the compiler automatically binds them to constant in increasing order (starting from 0 by default)
enum color { green =0 , red =1 , blue =2};
Part 4: Basic types
Enumerated types (2/2)
Values for constants of an enumeration may also be specified by the user:
enum color { green = 20 , red = -10 , blue };
/* blue == -9 */
enum spaces {
bell =’\ a ’, bspace =’\ b ’, newline =’\ n ’, creturn =’\ r ’, tab =’\ t ’, vtab =’\ v ’ };
Enumeration values may be equal:
enum color { green =20 , red = -10 , blue = -10};
Part 4: Basic types
Enumeration constant identifiers must be different across several enum types inside a scope
Variable declarations
Part 5: Variable declarations
Identifiers
Character set is a superset of ISO 646-1983 (and also trigraph notion)
Syntax
❍ Sequence of letters or digits (first character must be a letter)
❍ Underscore ” ” is considered as a letter
❍ Case sensitive
Examples:
ident Ident IDENT
foo x1 x123 _1234 foo_foo MAX __DATE__ (macros)
Part 5: Variable declarations
Keywords
32 keywords
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 volatile∗
do if static while
Note: * ANSI C.
Cannot be used as identifiers
Part 5: Variable declarations
Variable declarations
/* simple d e c l a r a t i o n s */
i n t x ; c h a r c ;
f l o a t foo1 , foo2 , foo3 ;
/* d e c l a r a t i o n s with i n i t i a l i z a t i o n */
u n s i g n e d i n t addr = 0 xFFFFu ; d o u b l e x1 , x2 = 123.45;
c h a r c1 = ’a ’, c2 = ’b ’, c3 = ’c ’;
/* c o n s t a n t d e c l a r a t i o n s */
c o n s t d o u b l e PI = 3 . 1 4 1 5 9 2 6 5 ; c o n s t max = 100; /* int by default */
/* with user defined types */
enum color { green , red , blue } light = red ; enum { empty , full } state ; /* a n o n y m o u s type */
const declarations declare variables which cannot be changed. Memory space is allocated!
Part 5: Variable declarations
Naming types: typedef
❍ typedef is used to give a name to a type
t y p e d e f i n t Integer ;
t y p e d e f enum { false , true } boolean ; t y p e d e f enum { green , red , blue } color ;
Integer i , j , k ; boolean b = true ; color light = blue ;
typedef does not define a new type, simply a syn- onym
Expression
Part 6: Expression
❍ Arithmetic operators
Integers Reals
Unary + - + -
Binary + - * / % + - * /
☞ no overflow checking
❍ Relational operators
== !=
> >= < <=
☞ type of operands: arithmetic or pointer type of result: int (0 or 1)
❍ Logical operators
|| && !
☞ type of operands: all scalar types type of result: int (0 or 1)
☞ the second operand is not evaluated, if the result can be deduced from the first
operand
Part 6: Expression
❍ Bitwise operators
~ | ^ &
☞ type of operands: int
❍ Shift operators
<< >>
☞ left shift is 0-filled
☞ right shift fills by 0 if its first operand is unsigned, otherwise fills (maybe) by copy of sign bit
❍ Conditional operator
☞ the only ternary operator of the language condition ? expr1 : expr2
min = a < b ? a : b;
Part 6: Expression
❍ Assignment operators – Simple assignment
=
operand types: arithmetic, pointer, struct or union
☞ result type: (non converted) left operand type
– Compound assignment
a op= b ⇔ a = a op b (a is only evaluated once)
+= -= *= /= %=
&= ^= |=
<<= >>=
– Incrementation - decrementation (by 1) x++ x-- (postfixed)
☞ result is value of x before
incrementation (or decrementation) ++x --x (prefixed)
☞ result is value of x after incrementation (or decrementation)
Part 6: Expression
❍ sizeof operator
sizeof expr or sizeof(type)
int a;
printf("%d %d\n",sizeof a, sizeof(int));
☞ expr is not evaluated, and object size must be computed at compile time
❍ Comma operator
expr1 , expr2 , ... exprn
☞ result is the value of the last expression (i.e. exprn)
– used when several expressions must be evaluated in some place where only one is permitted
f o r( i =0 , j = MAX ; i < j ; i ++ , j - -) { /* .... */
}
Part 6: Expression
Precedence and order of evaluation
16 () function call
16 [] indexation
16 . field selection
16 -> indirect field selection
15 ++ -- postfixed incr/decr
14 ++ -- prefixed incr/decr
14 sizeof size
14 (type) casting
14 ~ bitwise negation
14 ! negation
14 - opposite
14 & address of
14 * indirection
13 L * / % multiplicative operators
12 L + - additive operators
11 L << >> shifts operators
10 L < <= > >= relational operators
9 L == != equality operators
8 L & bitwise and
7 L ^ bitwise exclusive or
6 L | bitwise or
5 L && and
4 L || or
3 R ?: conditional
2 R = += -= *= /= %= assignments
2 R <<= >>= &= ^= |=
1 L , comma
Part 6: Expression
Implicit type conversions (1/2)
Applied when operand types of an expression are different.
Rules are rather complex!
❍ Unary conversions
integer types shorter than int ⇒ int signed integer types same size as int ⇒ int unsigned integer types same size asint ⇒ int
float ⇒ double (K&R)
❍ Binary conversions
1 if operands are not arithmetic
or same types ⇒ no conversion
2 if one op long double ⇒ long double
3 if one op double ⇒ double
4 if one op float ⇒ float
5 if one op unsigned long ⇒ unsigned long
6 if one op long ⇒ long
7 if one op unsigned int ⇒ unsigned int 8 else operand types are int ⇒ no conversion
Part 6: Expression
Implicit type conversions (2/2)
❍ Assignment conversions
type of left and right parts are identical ⇒ no conversion
left part right part
all arithmetic types all arithmetic types all pointer types integer constant 0 all pointer types void *
pointer to T array T pointer to function function
❍ Function parameter conversions Unary conversions are applied float ⇒ double
Part 6: Expression
Explicit conversions (cast)
(T) expression
to convert the result of expression into a value of type T
(i n t) 2.0 /* convert 2.0 to int ( i . e . 2) */
3 / (f l o a t) 4 /* = 0.75 whereas 3/4 = 0 */
no explicit conversion to struct or union integer ⇒ integer
real ⇒ integer
pointer ⇒ integer
real ⇒ real
integer ⇒ real pointer ⇒ pointer
integer ⇒ pointer (0 and void *) array ⇒ pointer (implicit) function ⇒ pointer (implicit) any type ⇒ void (but unusable)
Statements
Part 7: Statements
Elementary statement
expression;
; is an instruction terminator
to define an empty statement just put a ; w h i l e (( c = getchar ()) != SPACE )
/* do nothing */ ;
Part 7: Statements
Compound statement
{
[ list of declarations ] [ list of statements ] }
- to group several statements
w h i l e (a < b ) { a ++; b - -;
}
- to define local variables
i f (x >0) { f l o a t a , b ; a = x ; /* .... */
}
- to delimit a function body
Part 7: Statements
i n t main (v o i d) { /* ....} */
Part 7: Statements
If statement (1/2)
☞ i f ( l o g i c a l _ e x p r e s s i o n ) i n s t r u c t i o n
i f ( l o g i c a l _ e x p r e s s i o n ) i n s t r u c t i o n
e l s e
i n s t r u c t i o n
☞
☞ use a compound statement if several statements are needed in a branch
☞ logical expression is an integer expression which value is:
0 ⇔ false
not 0 ⇔ true
Part 7: Statements
If statement (2/2)
i f ( x == 0) y = 0;
i f ( x > y ) max = x ; e l s e max = y ;
i f ( isdigit ( c )) {
printf (" c is a digit \ n ");
n = c - ’0 ’; }
i f ( x == 1) i f ( y == 1)
printf (" x and y are equal to one \ n ");
e l s e
a = b = 0;
i f ( x == 1) { i f ( y == 1)
printf (" x and y are equal to one \ n ");
} e l s e
a = b = 0;
Part 7: Statements
Switch statement (1/2)
☞ s w i t c h ( i n t e g e r _ e x p r e s s i o n ) { c a s e value1: [ i n s t r u c t i o n s1 ] c a s e value2: [ i n s t r u c t i o n s2 ] ...
c a s e valuen: [ i n s t r u c t i o n sn ] [ d e f a u l t: [ i n s t r u c t i o n sn+1 ] ] }
❍ the switch expression value is an integer or enum
❍ case label values are constant expressions compatible with the switch expression
❍ switch exit with break (or return, goto, ...) instruction.
Part 7: Statements
Switch statement (2/2)
i n t c ;
s w i t c h ( c ) {
c a s e ’_ ’: printf (" For C , ’_ ’ is a ");
c a s e ’a ’: c a s e ’A ’:
.. . c a s e ’z ’:
c a s e ’Z ’: printf (" letter \ n ");
b r e a k; c a s e ’ ’:
c a s e ’\ n ’:
c a s e ’\ t ’: printf (" space \ n ");
b r e a k;
d e f a u l t: printf (" other character \ n ");
}
Part 7: Statements
Loops (1/2)
w h i l e ( l o g i c a l _ e x p r e s s i o n ) i n s t r u c t i o n
do i n s t r u c t i o n
w h i l e ( l o g i c a l _ e x p r e s s i o n );
f o r ( i n i t i a l i z a t i o n ; c o n d i t i o n ; i n c r e m e n t ) i n s t r u c t i o n ;
The For loop is strictly equivalent to:
i n i t i a l i z a t i o n ;
w h i l e ( c o n d i t i o n ) { i n s t r u c t i o n ;
i n c r e m e n t ; }
Part 7: Statements
Loops (2/2)
i = 1;
w h i l e ( i < MAX ) { n *= i ;
i ++;
}
i = 1; j = MAX ; do {
i ++; j - -;
} w h i l e ( i < j );
f o r( i = 1; i < MAX ; i ++) n *= i ;
Part 7: Statements
f o r( ; ; )
/* infinite loop */;
Part 7: Statements
Break statement
❍ Used to exit from a switch or a loop statement
w h i l e (1) { /* ... */
i f ( e x c e p t i o n ) b r e a k; /* ... */
}
f o r( i = 0; i < MAX ; i ++) i f ( t [ i ] == item ) b r e a k;
Part 7: Statements
f o r( i = 0; i < MAX ; i ++) s w i t c h ( t [ i ]) {
c a s e 0: /* .... */;
c a s e 1: b r e a k; /* probably wrong */
/* .... */
}
Part 7: Statements
Continue statement
❍ Used in loops
❍ Go to the next iteration
❍ In for loop, incrementation part is done first
❍ In while and do loops, test part is executed immediatly
f o r( i = 0; i < MAX ; i ++) { i f ( t [ i ] < 0) c o n t i n u e; /* ... */
}
Part 7: Statements
w h i l e ( i ++ < MAX ) { s w i t c h ( t [ i ]) {
c a s e 0: /* .... */; c a s e 1: c o n t i n u e; /* .... */
}
/* .... */
}
Part 7: Statements
Goto statement
❍ To avoid
❍ But exceptions
{
/* ... */
i f ( e x c e p t i o n ) g o t o Error ; /* ... */
/* ... */
Error : /* ... */; }
The preprocessor (1)
Part 8: The preprocessor (1)
❍ Called before the compiler proper
❍ Directives start with a sharp
#command-name [ arguments ]
❍ Main functions:
– macro definitions and replacement (#define)
– file inclusion (#include)
– conditional compilation (#if, #ifdef,
#ifndef)
❍ To write a multi-line directive use a backslash (\)
❍ E option of gcc to stop after the preprocessing stage
Part 8: The preprocessor (1)
Simple macro definition
❍ To define constants
❍ #define identifier character sequence
#d e f i n e FALSE 0
#d e f i n e EOF ( -1)
#d e f i n e PI 3 . 1 4 1 5 9 2 6 5 3
#d e f i n e SIZE 1024
#d e f i n e SIZE2 (2 * SIZE )
#d e f i n e begin {
#d e f i n e end ;}
#d e f i n e then
#d e f i n e p r o c e d u r e v o i d
❍ One may forget a macro definition
#u n d e f SIZE
#u n d e f then
Part 8: The preprocessor (1)
Simple macro replacement
❍ replacement is only textual
i n t buf [ SIZE ] , big_buf [ SIZE2 ];
p r o c e d u r e foo (v o i d) begin
i f ( x < SIZE ) then begin x ++; z ++
end end
After pre-processing:
i n t buf [1024] , big_buf [(2 * 1024)];
v o i d foo (v o i d) {
i f ( x < 1024) { x ++; z ++
;}
Part 8: The preprocessor (1)
Definition in compilation command line
❍ D compiler option provides a way to define macros without modifying the source file
% gcc -ansi -DMAXSIZE=100 -DDEBUG file.c
Part 8: The preprocessor (1)
Predefined macros
DATE current compilation date of source file TIME current compilation time of source file FILE current source file name
LINE current source file line number STDC must be defined in ANSI C
❍ These macros cannot be redefined or undefined
Part 8: The preprocessor (1)
Inclusion of source files
❍ Two notations
#include "filename"
#include <filename>
❍ The first one researches the file in the current directory, and in case of failure, in the
standard directories
❍ The second form researches only in the standard directories
#i n c l u d e " mine . h "
#i n c l u d e " ../../ stack . h "
#i n c l u d e < stdio .h >
#i n c l u d e < sys / stat .h >
#i n c l u d e " stdio . h "
☞ an included file may itself contain inclusion directives
Functions
Part 9: Functions
Function definition (1/3)
❍ Traditional form (K&R)
[result_type] fname([arg_list]) [arg_types]
{
[local declarations]
[instructions]
}
i n t max (a , b ) i n t a , b ; {
r e t u r n a > b ? a : b ; }
❍ This form is now obsolete
Part 9: Functions
Function definition (2/3)
❍ ANSI C form
result_type fname(arg_decl_list) {
[local declarations]
[instructions]
}
i n t max (i n t a , i n t b ) {
r e t u r n a > b ? a : b ; }
❍ No embedded functions
a function without argument is declared f() in K&R style, and f(void) in ansi style.
Part 9: Functions
Function definition (3/3)
❍ Result type – void
– any scalar type: integer, real, pointer, enumeration
– structure and union
– but no array (only address) – default result type is int (K&R)
❍ Argument types
– any scalar type: integer, real, pointer, enumeration
– structure and union – array
the size may not be specified int strlen(char s[MAX]) int strlen(char s[])
– types of formal and effective arguments must be compatible
Part 9: Functions
Argument passing
❍ Only one transmission mode: by value
v o i d f (i n t x ) {
x ++;
printf (" In function f : % d \ n ", x );
}
i n t main (v o i d) {
i n t a = 1;
f ( a );
printf (" After call to f : % d \ n ", a );
r e t u r n E X I T _ S U C C E S S ; }
In function f: 2 After call to f: 1
Part 9: Functions
❍ Evaluation order of arguments is not guaranteed
Part 9: Functions
Argument matching
❍ Formal arguments: implicit unary conversion (if needed)
❍ (K&R): no checks on effective arguments (number and type)
❍ ANSI C: the number and type of effective arguments are checked
Part 9: Functions
v o i d f (a , b ) /* K & R form */
i n t a ; d o u b l e b ; { }
v o i d g (i n t a , d o u b l e b ) /* ANSI form */
{ }
i n t main (v o i d) {
f (1); /* no c o m p i l a t i o n error */
f (1 ,2 ,4 ,5); /* no c o m p i l a t i o n error */
f (" abc ", " zzz "); /* no c o m p i l a t i o n error */
f (1.5 ,2); /* p o t e n t i a l problem */
f (1 ,2); /* p o t e n t i a l problem */
g (1); /* c o m p i l a t i o n error */
g (1 ,2 ,4 ,5); /* c o m p i l a t i o n error */
g (" abc ", " zzz "); /* c o m p i l a t i o n error */
g (1.5 ,2); /* 1.5 is c o n v e r t e d into int */
g (1 ,2); /* 2 is c o n v e r t e d into double */
}
Part 9: Functions
Returning from a function
Return statement: return [expr];
❍ return statement may appear anywhere in the function body
❍ if function result type is void, expr is omitted
❍ if function result type is void, and there is no return statement, a default return is
implicitly set at the end of the function body
❍ if function result type is T, expr must exist and be of (converted, if possible) T type
i n t f (v o i d) {
r e t u r n 12.6;
/* that is return ( int ) 12.6 ( i . e . 12) */
}
Part 9: Functions
Variables (1/4)
❍ Global variable
Definition: outside any block
Lifetime: static = the whole program execution
Scope: from the declaration place to the end of the file (unless masked)
❍ Local variable
Definition: inside a block (variables declared in main function are local)
Lifetime: automatic = execution time of the block
Scope: the block and any nested blocks (unless masked)
Part 9: Functions
Variables (2/4)
i n t a ;
v o i d f (v o i d) { i n t b ;
x ++; /* x is unknown */
a ++; /* incrementi ng global variable */
b ++; /* incrementi ng local variable */
}
i n t x ;
i n t main (v o i d) {
i n t a ; /* mask global variable */
x ++; /* incrementi ng global variable */
a ++; /* incrementi ng local variable */
r e t u r n E X I T _ S U C C E S S ; }
Part 9: Functions
Variables (3/4)
❍ Static variable
Definition: inside a block, prefixed by static
Lifetime: the whole program execution Scope: the block and any nested blocks (unless masked)
❍ Register variable
Definition: inside a block (argument or variable), prefixed by register
Lifetime: execution time of the block Scope: the block and any nested blocks (unless masked)
Note: set in register if possible (only scalar values)
Part 9: Functions
Variables (4/4)
i n t f (v o i d) {
r e g i s t e r i n t c ; s t a t i c i n t x = 0;
w h i l e (( c = getchar ()) != EOF ) putchar ( c );
r e t u r n x ++;
}
i n t main (v o i d) {
printf (" % d % d \ n ", f () , f ());
/* ⇒ 1 0 */
r e t u r n E X I T _ S U C C E S S ; }
Part 9: Functions
Function declarations
❍ Function declaration = to give its prototype (i.e. its header)
Useful if one calls
- a function defined later in the same source file
- a function defined in another source file
❍ Two forms:
K&R: type fname();
ex: double cos();
ANSI C: type fname(arg type list);
ex: double cos(double);
❍ If neither the definition nor the declaration of the function are available, the compiler
performs an implicit declaration assuming int as return type and no arguments checking
Part 9: Functions
Variable number of arguments (1/2)
❍ List of arguments denoted by ... after the last named argument (one at least)
❍ A set of macros
#include <stdarg.h>
va start(va list ap, last named parameter) va arg(va list ap, type)
va end(va list ap)
/* va_list ap represents the current argument*/
Part 9: Functions
Variable number of arguments (2/2)
#i n c l u d e < stdarg .h >
i n t max (i n t first , ...)
/* return the maximum of p o s i t i v e i n t e g e r s ; the list ending up with -1
*/
{
i n t maxi = 0;
va_list ap ; /* current a r g u m e n t */
va_start ( ap , first );
w h i l e ( first != -1) {
i f ( first > maxi ) maxi = first ; first = va_arg ( ap , i n t);
}
va_end ( ap );
r e t u r n maxi ; }
i n t main (v o i d) {
x = max (2 , 56 , 67 , 1 , 16 , -1);
x = max (12 , 14 , 4 , -1 , 20 , 30 , -1);
}
Arrays
Part 10: Arrays
Characteristics
❍ Only one dimension
❍ Multi-dimensional arrays are represented by arrays of arrays
❍ Integer index only
❍ Low bound is always 0
❍ Index within the bounds of array’s index range IS NOT checked at running time!
❍ Can be initialized with aggregates
❍ C compiler must be able to calculate statically the size of the array
Part 10: Arrays
i n t t [10]; /* t [0] t [1] ... t [9] */
f l o a t m [3][8];
/* m [0][0] m [0][1] ... m [0][7]
m [1][0] m [1][1] ... m [1][7]
m [2][0] m [2][1] ... m [2][7]
*/
Part 10: Arrays
Initialization
c h a r t [4] = { ’A ’, ’B ’, ’C ’, ’D ’ };
f l o a t m [2][3] = { { 0.0 , 0.1 , 0.2 } , { 1.0 , 1.1 , 1.2 }};
❍ Missing elements are initialized to 0
c h a r t [4] = {’A ’, ’B ’}; /* t [2]== t [3]== ’\0 ’ */
f l o a t m [2][3] = { { 0.0 } ,
{ 1.0 , 1.1 , 1.2 }};
/* m [0][1] == m [0][2] == 0.0 */
❍ First dimension can be omitted, size of array is automatically calculated by the compiler
Part 10: Arrays
c h a r t [] = { ’A ’, ’B ’, ’C ’, ’D ’ };
i n t m [][3] = { { 0 , 1 , 2 } , { 3 , 4 }
{ 5 } };
/* m = ‘\ tmpmat {} ‘ */
Part 10: Arrays
String (1/3)
❍ Array of char
❍ String litteral constants are in double quotes
❍ Ends with a nul character (’\0’) sizeof "abc"== 4
❍ It is not a type by itself
c h a r s1 [10] = {’1 ’,’2 ’,’3 ’,’4 ’,’ \0 ’};
c h a r s2 [10] = " 1234 ";
" I ’m a string "
" " /* an empty string */
" \ t \" Hello World \"\ n "
" a multi - line ...\
string !!! "
Part 10: Arrays
String (2/3)
❍ C compiler automatically sets ’\0’ at the end of litteral string constant
❍ Don’t forget to set it when defining string from array of characters
❍ No predefined operators on strings
❍ Standard library provides a lot of string functions (concatenation, copy, ...) ; string.h
❍ These string functions do not manage memory space allocation (except strdup)
Part 10: Arrays
String (3/3)
i n t strlen (c h a r s [])
/* calculate the length of the string s */
{
i n t i = 0;
w h i l e ( s [ i ] != ’ \0 ’) i ++;
r e t u r n i ; }
Part 10: Arrays
v o i d strcpy (c h a r s1 [] , c h a r s2 []) /*
copy the string pointed to by s2 to the string pointed to by s1
*/
{
i n t i = 0;
w h i l e (( s1 [ i ] = s2 [ i ]) != ’ \0 ’) i ++;
}
Structures and Unions
Part 11: Structures and Unions
Structures (1/3)
❍ Collection of objects, which may be of different types
❍ Called records in Pascal
s t r u c t complexe { d o u b l e real , imag ; };
s t r u c t complexe x , y ;
s t r u c t {
/* anonymous type */
i n t day , month , year ; c h a r m o n t h _ n a m e [10];
} d ;
t y p e d e f s t r u c t { d o u b l e real , imag ; } complexe ;
Part 11: Structures and Unions
Structures (2/3)
❍ Variables of struct type can be initialized with aggregates
– K&R: only static variables
– ANSI: static and automatic variables
Part 11: Structures and Unions
s t r u c t complexe { d o u b l e real , imag ; } x = { 1.4 , 3.5 };
s t r u c t {
/* anonymous type */
i n t day , month , year ; c h a r m o n t h _ n a m e [10];
} d = { 2 , 3 , 1997 , " March " } ; s t r u c t S1 {
i n t x ;
s t r u c t { d o u b l e d ; c h a r c ; } y ; i n t z [5];
};
s t r u c t S1 x = { 1 , { 10.9 } };
/*
same as struct S1 x =
{ 1 , { 10.9 , ’\0 ’} , { 0 , 0 , 0 , 0 , 0 } };
*/
Part 11: Structures and Unions
Structures (3/3)
❍ Field access: member operator “.”
s t r u c t complexe x ;
x . real = 12.5; x . imag = 0.5;
i n t leap (s t r u c t date d ) {
r e t u r n d . year % 4 == 0 && d . year % 100 != 0
|| d . year % 400 == 0;
}
s t r u c t person {
c h a r name [ NAMESIZE ];
l o n g i n t n_insee ; s t r u c t date b i r t h d a t e ; } p ;
strcpy ( p . name ," John ");
p . b i r t h d a t e . year = 1986;
Part 11: Structures and Unions
Bit fields
❍ Bit fields can be used to access memory word at bit level
❍ Fields have to be unsigned integer values within a machine word
000000 000000 000 111111 111111 111
segment
s page offset
31 29 23 15 0
Virtual address on XBQ-43
s t r u c t virtual \ _address { u n s i g n e d offset : 16;
u n s i g n e d page : 8;
u n s i g n e d segment : 6;
u n s i g n e d : 1; /* unused */
u n s i g n e d s u p e r v i s o r : 1;
};
❍ Portabililty problem
Part 11: Structures and Unions
Unions (1/4)
❍ Unions provide type union
❍ Variants in Pascal records
u n i o n S t r i n g I n t {
c h a r string [ MAXSIZE ];
i n t i ; };
u n i o n S t r i n g I n t x , y ;
But also
Part 11: Structures and Unions
u n i o n S t r i n g I n t {
c h a r string [ MAXSIZE ];
i n t i ; } x , y ; u n i o n {
/* anonymous type */
c h a r string [ MAXSIZE ];
i n t i ; } x , y ;
Part 11: Structures and Unions
Unions (2/4)
❍ Static variables of union type can be initialized with aggregates in ANSI C
❍ Only the first member is initialized
enum sexe { m , f };
s t a t i c u n i o n {
s t r u c t { enum sexe kind ; i n t shape ; } X ; s t r u c t { enum sexe kind ; d o u b l e shape ; } Y ; } U = { f , 100 };
Part 11: Structures and Unions
Unions (3/4)
❍ Field access with member operator ”.”
❍ Only one member is accessible at a time
u n i o n { i n t i , d o u b l e d } u ;
u . i = 20; /* access to u . d allowed , but u n d e f i n e d */
...
u . d = 1.1; /* access to u . i allowed , but u n d e f i n e d */
❍ Use a selector
Part 11: Structures and Unions
s t r u c t person {
c h a r l a s t _ n a m e [20] , f i r s t _ n a m e [20];
s t r u c t date b i r t h d a t e ;
enum { f , m } sexe ; /* s e l e c t o r */
u n i o n {
c h a r m a i d e n _ n a m e [20];
enum { false , true } army ; } info ;
} p ;
p . sexe = f ; strcpy ( p . info . maiden_name ," Monroe ");
p . sexe = m ; p . info . army = false ;
Part 11: Structures and Unions
Unions (4/4)
❍ Size of an union object = memory space for representing its largest member (+ eventually alignment requirements)
struct {
};
double c;
int b;
char a;
c union {
};
double c;
int b;
char a;
000000 000000 000000 000000 000000 000000
111111 111111 111111 111111 111111 111111
000000 000000 000000 111111 111111 111111 00000000
00000000 11111111 11111111
char = 8 bits, int = 32 bits, double = 64 bits
a b
a b
c
Pointers
Part 12: Pointers
❍ A pointer contains the address of an object.
The access to the pointed object is thus performed indirectly
❍ Pointers are typed ⇒ Compatiblity needed for assignment!
❍ Conversions
– implicit to any pointer to void * (and back)
– any other pointer types need an explicit cast
❍ #define NULL ((void *) 0) in <stddef.h>
❍ Heavy use of pointers. Programs are – more compact
– more efficient
– but far less readable!
– but error prone!
Part 12: Pointers
Examples
i n t * p1 , * p2 ; /* two p o i n t e r s to integer */
c h a r * p3 , p4 ; /* one pointer to char , one char */
c h a r ** s ; /* pointer to pointer to char */
v o i d * r ; /* pointer to void ( generic ) */
f l o a t * s [10] /* array of 10 p o i n t e r s to real */
f l o a t (* t )[10] /* pointer to an array of 10 reals */
i n t (* pfunc )(v o i d); /* pointer to f u n c t i o n with no argument , r e t u r n i n g an int */
i n t (* T [5])(v o i d); /* array of 5 such p o i n t e r s */
Part 12: Pointers
Basic operations on pointers
❍ * indirection (dereferencing)
❍ & address of (referencing)
i = 10;
pi = &i;
j = *pi;
(*pi)++;
q = pi;
pi i j q
10
10 10
10
11 10
10 11
{ int *pi, i, j, *q = NULL;
}
Part 12: Pointers
Arithmetic operators on pointers
❍ Comparison: == != < <= > >=
❍ Adding/substracting an integer:
– pointer + integer → pointer – pointer − integer → pointer – address scaling
❍ Substracting two pointers of same type – pointer − pointer → integer
– the result is an algebraic number of objects of the type
Part 12: Pointers
Pointers and arrays (1/2)
❍ Pointers and arrays are closely related concepts
❍ An array is a constant pointer to the first element of the array
❍ t[i] ⇔ *(t+i)
❍ t[i][j] ⇔ *(*(t+i)+j)
i n t *p , t [8];
c h a r * s = " hello "; c h a r st [] = " hello ";
p = t ;
p = & t [0]; /* idem as above */
/*
t [2]==*( t +2)==*( p +2)== p [2]
s [2]==*( s +2)==*(" hello "+2)==" hello "[2]
*/
Part 12: Pointers
Pointers and arrays (2/2)
❍ Difference between arrays and pointers
e l l o \0 h
t
e l
h l o \0
char *p = "hello";
char t[8] = "hello";
p
p ++; /* OK */
t ++; /* KO */
printf (" % d % d \ n ",s i z e o f( p ) ,s i z e o f( t ));
/* 4 8 */
Part 12: Pointers
Pointers and structures
❍ It is illegal for a structure to reference itself
❍ Recursive declarations use pointers
s t r u c t list { i n t item ;
s t r u c t list * next ; } * l ;
❍ Access to structure (or union) members: ->
l->item is equivalent to (*l).item
Part 12: Pointers
String functions with pointers
i n t strlen (c o n s t c h a r * s )
/* calculate the length of a string s */
{
c h a r * p = s ;
w h i l e (* s ++) /* empty body */; r e t u r n (s -1) - p ;
}
Part 12: Pointers
c h a r * strcpy (c h a r * s1 , c o n s t c h a r * s2 ) /*
copy the string pointed to by s2 to the string pointed to by s1
*/
{
c h a r * p = s1 ;
w h i l e (* s1 ++ = * s2 ++) /* empty body */; r e t u r n p ;
}
Part 12: Pointers
Simulating call by reference
❍ When a function needs to return more than one result
v o i d swap (i n t *a , i n t * b ) {
i n t aux ;
aux = * a ; * a = * b ; * b = aux ; } ...
i n t x , y ; ...
swap (& x , & y ); /* function call */
❍ Array is a pointer. There is no copying of array elements!
Part 12: Pointers
v o i d reset (f l o a t t [] , i n t n ) /* reset the t array to 0 */
{
i n t i = 0;
w h i l e (i < n ) t [ i ++] = 0.0;
}
f l o a t ftab [ MAX ];
...
reset ( ftab , MAX ); /* function call */
Part 12: Pointers
Pointers and constants
❍ Constant pointer. Need to be initialized at declaration time
i n t * c o n s t pconst = & x ;
❍ Pointer to constant object. The object cannot be modified through the pointer
c o n s t i n t * pconst ;
❍ Constant pointer to constant object
c o n s t i n t * c o n s t p c o n s t _ t o _ c o n s t = & x ;
c o n s t i n t i = 1;
i n t * p = & i ; /* wrong */