C Programming
C Programming
com
Introduction
y Developed between 1969 and 1973 along with Unix y Due mostly to Dennis Ritchie y Designed for systems programming y Operating systems y Utility programs y Compilers y Filters
#include inserts another file. .h files are called header files. They contain stuff needed to interface to libraries and code in other .c files. Can your program have
more than one .c file?
The main() function is always where your program starts running. Blocks of code ( lexical scopes ) are marked by {
1. Write text of program (source code) using an editor such as emacs, save as file e.g. my_program.c 2. Run the compiler to convert program from source to an executable or binary : $ gcc Wall g my_program.c o my_program
$ gcc -Wall g my_program.c o my_program tt.c: In function `main': tt.c:6: parse error before `x' tt.c:5: parm types given both in parmlist and separately tt.c:8: `x' undeclared (first use in this function) tt.c:8: (Each undeclared identifier is reported only once tt.c:8: for each function it appears in.) tt.c:10: warning: control reaches end of non-void function tt.c: At top level: tt.c:11: parse error before `return'
-Wall g ?
3-N. Compiler gives errors and warnings; edit source file, fix it, and re-compile N. Run it and see if it works $ ./my_program Hello World $
my_program
4
Preprocess
__extension__ typedef __extension__ typedef __extension__ typedef __extension__ typedef __extension__ typedef __extension__ typedef __extension__ typedef __extension__ typedef
unsigned long long int unsigned int unsigned int __uid_t; __gid_t;
__dev_t;
__ino_t; __ino64_t;
__off_t; __off64_t; ; ; ;
In Preprocessing, source code is expanded into a larger form that is simpler for the compiler to understand. Any line that starts with # is a line that is interpreted by the Preprocessor. Include files are pasted in (#include) Macros are expanded (#define) Comments are stripped out ( /* */ , // ) Continued lines are joined ( \ )
\?
extern void flockfile (FILE *__stream) extern int ftrylockfile (FILE *__stream) extern void funlockfile (FILE *__stream) int main(int argc, char **argv) { printf(Hello World\n); return 0; }
my_program
Compile
5
The compiler then converts the resulting text into binary code the CPU can run directly.
Datatypes
y char a character y int an integer, in the range -32,767 to 32,767 y long int a larger integer (up to +-2,147,483,647) y float a floating-point number y double a floating-point number, with more precision
Memory allocation
Variable
A Variable names a place in memory where you store a Value of a certain Type. You first Define a variable by giving it a name and specifying the type, and optionally an initial value declare vs define?
char x; char y=e;
symbol table?
Symbol
Addr 0 1 2 3
Value
x y
4 5 6 7 8 9 10 11 12
? e (101)
Different types consume different amounts of memory. Most architectures store data on word boundaries , or even multiples of the size of a primitive data type (int, char)
char x; char y=e; int z = 0x01020304; 0x means the constant is written in hex padding
Multi-byte Variables
x y
Symbol
Addr 0 1 2 3 4 5 6 7 ?
Value
e (101)
z
An int consumes 4 bytes
8 9 10 11 12
4 3 2 1
Constants
y A constant is just an immediate, absolute value found
in an expression. y Simplest constants are decimal integers, e.g. 0, 1, 2, 123 y Char constant eg: char a= x ; y Enumeration
y Eg: enum boolean {NO ,Yes}; y Enum months {Jan=1, Feb ,March};
#define LOWER 0
operators
y Arithmetic operators y + addition y - subtraction y * multiplication y / division % y Modulus (remainder) y Increment &decrement operators y Pre y Post
x + 2 * 2
x + 4
1 + 4
Comparison operators are used to compare values. In C, 0 means false , and any other value means true .
int x=4; (x < 5) (x < 4) ((x < 5) || (x < 4)) (4 < 5) (4 < 4) (<true> || (x < 4)) <true> 0 <true>
13
Continue..
y Bitwise operators y & bitwise AND -> used to mask a value y Eg: 1110110 ( 0x 76) we need to mask 3rd bit y i=1110110 & 11110111 = 1110010 ; ( anything & with 1 remain same and & with 0 wil become 0 )
y
y | bitwise OR -> used to set bits /turn on. y Eg : 1110110 ( 0x 76) we need to set 4th bit y i=1110110 | 0001000 = 1111110 ; ( anything | with 0 remain
i=i | 0x76
Continue..
y ^ bitwise exclusive OR y << left shift -> shifts to their left operand by the
y >> right shift : fills the vacated bits with 0 y ~one s complement
The rules of precedence are clearly defined but often difficult to remember or non-intuitive. When in doubt, add parentheses to make it explicit. For oftconfused cases, the compiler will give you a warning Suggest parens around do it! Beware division: If second argument is integer, the result will be integer (rounded): 5 / 10 0 whereas 5 / 10.0 0.5 Division by 0 will cause a FPE Don t confuse & and &&.. 1 & 2 0 whereas 1 && 2 <true>
16
Assignment Operators
assign y to x post-increment x pre-increment x post-decrement x pre-decrement x x x x x x += -= *= /= %= y y y y y assign assign assign assign assign (x+y) (x-y) (x*y) (x/y) (x%y) int x=5; int y; y = x++; /* x == 6, y == 5 */
to to to to to
x x x x x
Don t confuse = and ==! The compiler will warn suggest parens .
int x=5; if (x==6) /* false */ { /* ... */ } /* x is still 5 */
18
recommendation
Control flow
y For statement y For ( initialization ; condition ; post body exec ) y while y If- else y Else-if y Switch y Break y goto
true
Boolean Expression
false
20
21
switch (ch) { case 'a': printf ( %c ); case 'b': printf ( %c ); case 'c': printf ( %c );; }
22
switch (ch) { case 'a': printf ( %c );; case 'b': printf ( %c ); case 'c': printf( %c ); } Next statement;
23
switch (ch) { case 'a': printf ( %c ); break; case 'b': printf ( %c ); break; case 'c': printf ( %c ); }
24
y Do-while
do
statement While {expression );
2 or more loops y Continue : never used in swicth & used to repeat iteration of a loop
Functions
y Functions Make your programs more modular and easier to understand with functions. y Can u define a function inside another function? Scope rules : y global variables -> stored in data section y Local variables -> on stack y Automatic variables -> on stack y Static variables -> stored in data section y Register variables -> in registers
Lexical Scoping
Every Variable is Defined within some scope. A Variable cannot be referenced by name (a.k.a. Symbol) from outside of that scope. Lexical scopes are defined with curly braces { }. The scope of Function Arguments is the complete body of the function. The scope of Variables defined inside a function starts at the definition and ends at the closing brace of the containing block The scope of Variables defined outside a function starts at the definition and ends at the end of the file. Called Global Vars.
27
(Returns nothing)
char b?
legal?
char d; /* p,z,q,a,b,d (not c) */ } /* p,z,q */
pointers
y Pointers are variables that store addresses y declaration: type *var y Operators: y & : address-of y * : dereference int i = 5; /* i is an int containing 5 */ int *p; /* p is a pointer to an int */ p = &i; /* p holds the address of i */ int j = *p; /* j gets what p points to */
int main () { int i, j, *p, *q; i = 10; p = &j; q = p; *q = i; *p = (*q) * 2; printf("i=%d, j=%d, *p=%d, *q=%d\n", i, j, *p, *q); } i=10, j=20, *p=20, *q=20
y #include <stdio.h> int main() { int x; /* A normal integer*/ int *p; /* A pointer to an integer ("*p" is an integer, so p must be a pointer to an integer) */ p = &x; /* Read it, "assign the address of x to p" */ scanf( "%d", &x ); /* Put a value in x, we could also use p here */ printf( "%d\n", *p ); /* Note the use of the * to get the value */ getchar(); }
Arrays
Arrays in C are composed of a particular type, laid out in memory in a repeating pattern. Array elements are accessed by stepping forward in memory from the base of the array by a multiple of the element size.
/* define an array of 10 chars */ char x[5] = {t,e,s,t,\0}; /* accessing element 0 */ x[0] = T; /* pointer arithmetic to get elt 3 */ char elt3 = *(x+3); /* x[3] */ /* x[0] evaluates to the first element; * x evaluates to the address of the * first element, or &(x[0]) */ /* 0-indexed for loop idiom */ #define COUNT 10 char y[COUNT]; int i; for (i=0; i<COUNT; i++) { /* process y[i] */ printf(%c\n, y[i]); } 32
Brackets specify the count of elements. Initial values optionally set in braces. Arrays in C are 0-indexed (here, 0..9) x[3] == *(x+3) == t
What s the difference between char x[] and char *x?
(NOT s !)
Symbol char x [0] char x [1] Addr 100 101 102 103 104 Value t e s t \0
Arrays in memory
integers
y Array: sequence of identical objects y int a[10]; means space for ten
Filippo Brunelleschi, Ospdale degli Innocenti, Firenze, Italy, 1421
By itself, a is the address of the first integer *a and a[0] mean the same thing The address of a is not stored in memory: the compiler inserts code to compute it when it appears Ritchie calls this interpretation the biggest conceptual jump from BCPL to C
Multidimensional Arrays
y Array declarations read right-to-left y int a[10][3][2]; y an array of ten arrays of three arrays of two ints
3 y In memory 3 ... 2 2 2 2 2 2 2 2 2 3
10
Structures
struct: a way to compose existing types into a structure
#include <sys/time.h> /* declare the struct */ struct my_struct { int counter; float average; struct timeval timestamp; uint in_use:1; uint8_t data[0]; };
Packing?
struct timeval is defined in this header structs define a layout of typed fields structs can contain other structs
Why?
fields can specify specific bit widths A newly-defined structure is initialized using this syntax. All unset fields are 0.
/* define an instance of my_struct */ struct my_struct x = { in_use: 1, timestamp: { tv_sec: 200 } }; x.counter = 1; x.average = sum / (float)(x.counter); struct my_struct * ptr = &x; ptr->counter = 2; (*ptr).counter = 3; /* equiv. */ 35
Fields are accessed using . notation. A pointer to a struct. Fields are accessed using -> notation, or (*ptr).counter
especially for arrays y Pad to ensure alignment of largest object (with biggest requirement)
C Unions
y Can store objects of different types at different times
Libraries
y String libraries y Math libraries
files
C Storage Classes
#include <stdlib.h> int global_static; static int file_static; void foo(int auto_param) { static int func_static; int auto_i, auto_a[10]; double *auto_d = malloc(sizeof(double)*5); }
C Storage Classes
#include <stdlib.h> int global_static; static int file_static;
Space allocated on stack by caller.
Space allocated on stack void foo(int auto_param) by function. { static int func_static; int auto_i, auto_a[10]; double *auto_d = Space allocated on heap by malloc(sizeof(double)*5); routine. library }
any order
y Common source of errors y Using uninitialized memory y Using freed memory y Not allocating enough y Neglecting to free disused blocks (memory leaks)
company (Pure Software) founded to sell tool to track them down y Purify tool inserts code that verifies each memory access y Reports accesses of uninitialized memory, unallocated memory, etc. y Publicly-available Electric Fence tool does something similar
malloc(
Memory Pools
y An alternative: Memory pools y Separate management policy for each pool y Stack-based pool: can only free whole pool at once y Very cheap operation y Good for build-once data structures (e.g., compilers) y Pool for objects of a single size y Useful in object-oriented programs y Not part of the C standard library