Sei sulla pagina 1di 52

Ayeesha Masrath ayeesha.masrath@gmail.

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

C Syntax and Hello World


What do the < > mean?

#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?

This is a comment. The compiler ignores this.


#include <stdio.h> /* The simplest C Program */ int main(int argc, char **argv) { printf(Hello World\n); return 0; }

The main() function is always where your program starts running. Blocks of code ( lexical scopes ) are marked by {

Return 0 from this function


3

Print out a message. \n means new line .

Writing and Running Programs


#include <stdio.h> /* The simplest C Program */ int main(int argc, char **argv) { printf(Hello World\n); return 0; }

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 $

./? What if it doesn t work?

my_program
4

A Quick Digression About the Compiler


#include <stdio.h> /* The simplest C Program */ int main(int argc, char **argv) { printf(Hello World\n); return 0; }

Preprocess

Compilation occurs in two steps: Preprocessing and Compiling


Why ?

__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;

unsigned long int

__ino_t; __ino64_t;

unsigned long long int unsigned int long int __nlink_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 ( \ )
\?

long long int

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

and perhaps greater range than float

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)

Initial value of x is undefined

Initial value Name


What names are legal?

The compiler puts them somewhere in memory.

Type is single character (char)


extern? static? const?
8

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

Lets look at the Code

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};

y Symbolic constant y Eg: #define name repalcement_txt


y

#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

Expressions combine Values using Operators, according to precedence.


1 + 2 * 2 (1 + 2) * 2 1 + 4 3 * 2 5 6

Expressions and Evaluation

Symbols are evaluated to their Values before being combined.


int x=1; int y=2; x + y * y

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

Not evaluated because first clause was true

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

i=i & 0x76

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

same and | with 1 wil become 1 )


y

i=i | 0x76

Continue..
y ^ bitwise exclusive OR y << left shift -> shifts to their left operand by the

number of bit positions given by the right operand


y Eg: x << 2

y >> right shift : fills the vacated bits with 0 y ~one s complement

Comparison and Mathematical Operators


== < <= > >= != && || ! + * / % equal to less than less than or equal greater than greater than or equal not equal logical and logical or logical not plus minus mult divide modulo & | ^ ~ << >> bitwise and bitwise or bitwise xor bitwise not shift left shift right

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 & Expressions


y General format : y Expr1 op=expr2 equivalent to Expr1 =(expr1 ) op (expr2 ) y Eg: i= i+2; y i+=2 ; - assignment operator y Conditional Expressions The statements If (a > b) z=a; Else z=b;
Can be written using ternary operator ?: as expr 1 ? Expr 2 : expr 3 Z= (a>b) ? a:b

x = y x++ ++x x---x

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

Note the difference between ++x and x++:


int x=5; int y; y = ++x; /* x == 6, y == 6 */

Don t confuse = and ==! The compiler will warn suggest parens .
int x=5; if (x==6) /* false */ { /* ... */ } /* x is still 5 */
18

int x=5; if (x=6) /* always true */ { /* x is now 6 */ } /* ... */

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

if (booleanExpression) { statement(s)-for-the-true-case; } else { statement(s)-for-the-false-case; }

The if...else Statement

true

Boolean Expression

false

Statement(s) for the true case

Statement(s) for the false case

20

Trace if-else statement


Suppose score is 70.0 if (score >= 90.0) grade = 'A'; else if (score >= 80.0) grade = 'B'; else if (score >= 70.0) grade = 'C'; else if (score >= 60.0) grade = 'D'; else grade = 'F'; The condition is false

21

Trace switch statement


Suppose ch is 'a':

switch (ch) { case 'a': printf ( %c ); case 'b': printf ( %c ); case 'c': printf ( %c );; }

22

Trace switch statement


Execute next statement

switch (ch) { case 'a': printf ( %c );; case 'b': printf ( %c ); case 'c': printf( %c ); } Next statement;

23

Trace switch statement


Suppose ch is 'a':

switch (ch) { case 'a': printf ( %c ); break; case 'b': printf ( %c ); break; case 'c': printf ( %c ); }

24

y Do-while

do
statement While {expression );

y Goto : used in deeply nested statements to break out of

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)

void p(char x) { /* char y; /* char z; /* } /* char z; /*

p,x */ p,x,y */ p,x,y,z */ p */ p,z */

void q(char a) { char b; /* p,z,q,a,b */ { char c; /* p,z,q,a,b,c */ }

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

For loop that iterates from 0 to COUNT-1. Memorize it!

char x [2] char x [3] char x [4]

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

Seagram Building, Ludwig Mies van der Rohe,1957

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

Alignment of data in structs


y Compilers add padding to structs to ensure proper alignment,
a c Pad a b b b b c

especially for arrays y Pad to ensure alignment of largest object (with biggest requirement)

struct { char a; int b; char c; }

y Moral: rearrange to save memory

C Unions
y Can store objects of different types at different times

union { int ival; float fval; char *sval; };


y Useful for arrays of dissimilar objects y Potentially very dangerous y Good example of C s philosophy y Provide powerful mechanisms that can be abused

Alignment of data in structs


y Compilers add padding to structs to ensure proper alignment, especially for arrays y Pad to ensure alignment of largest object (with biggest a requirement)
b b b b c Pad a b b b b c

struct { char a; int b; char c; }

y Moral: rearrange to save memory

Libraries
y String libraries y Math libraries

files

Linker-visible. Allocated at fixed location

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); }

Visible within file. Allocated at fixed location.

Visible within func. Allocated at fixed location.

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 }

malloc() and free()


y Library routines for managing the heap

int *a; a = (int *) malloc(sizeof(int) * k); a[5] = 3; free(a);


y Allocate and free arbitrary-sized chunks of memory in

any order

malloc() and free()


y More flexible than automatic variables (stacked) y More costly in time and space y malloc() and free() use complicated non-constant-time algorithms y Each block generally consumes two additional words of memory
y y

Pointer to next empty block Size of this block

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)

malloc() and free()


y Memory usage errors so pervasive, entire successful

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

Dynamic Storage Allocation


y What are malloc() and free() actually doing? y Pool of memory segments:
Free

malloc(

Dynamic Storage Allocation


y Rules: y Each segment contiguous in memory (no holes) y Segments do not move once allocated y malloc() y Find memory area large enough for segment y Mark that memory is allocated y free() y Mark the segment as unallocated

Dynamic Storage Allocation


y Three issues: y How to maintain information about free memory

y The algorithm for locating a suitable block

y The algorithm for freeing an allocated block

Simple Dynamic Storage Allocation


y Three issues: y How to maintain information about free memory y Linked list y The algorithm for locating a suitable block y First-fit y The algorithm for freeing an allocated block y Coalesce adjacent free blocks

Simple Dynamic Storage Allocation


Next Size Size Free block Next Size Allocated block malloc( ) First large-enough free block selected Free block divided into two Previous next pointer updated Newly-allocated region begins with a size value

Dynamic Storage Allocation


y Many, many variants y Other fit algorithms y Segregation of objects by sizes y 8-byte objects in one region, 16 in another, etc. y More intelligent list structures

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

Potrebbero piacerti anche