slide: 1 camp 06: maturing minds programming in c recap camp 06 maturing minds

37
CAMP 06: Maturing Minds Slide: 1 Programming in C Recap Camp 06 Maturing Minds

Upload: kimberly-steele

Post on 26-Mar-2015

224 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 1

Programming in C

Recap

Camp 06Maturing Minds

Page 2: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 2

Goals

• We review different constructs of C language

• We discuss typical syntactic and semantic pitfalls

• We discuss some complex programming concepts like function pointers

• We discuss some guidelines that will help you in writing good C code

Page 3: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 3

How big is an integer?

• ‘long’ is not always 32 bits.

• ‘int’ is not always 32 bits.

• The only truth is:

sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)

• sizeof(char) is always 1.

• Sizes of float, double variables are implementation dependent.

Page 4: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 4

What happens when an integer operation overflows?

• If either operand is unsigned, the result is unsigned and is defined to be modulo 2n.

• If both operands are signed, the result is undefined.

• a and b are two big integers which are multiplied to obtain a number that may be stored in a long. The following, however, is incorrect. long c = a * b; //Why?

Integer overflow

// a and b are int [positive]if ((a + b) < 0) complain(); //might not work

if ((int) ((unsigned)a + (unsigned)b) < 0) complain(); // will work

Page 5: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 5

Are characters signed?

• Whether it is signed or unsigned is implementation dependent.

• Still, for programming purposes ‘char’ is neither ‘signed char’ nor ‘unsigned char’.

Page 6: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 6

Operator precedence

Operator precedence may give surprises sometimes.

if (flags & OF_FLAG != 1) {...}; // what does this mean?

!= binds more tightly than &.

if ((flags & OF_FLAG) != 1) {...};

Use braces properly in expressing yourself

Page 7: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 7

Operator precedence

Two int vars, ‘h’ and ‘l’ are in [0,15] range. ‘r’ is formed as (h,l).

r = h<<4 + l; // is it correct?

r = h << (4 + l); //same as above

+ binds more tightly than <<. Don’t trust spaces!!! Trust braces.

r = (h << 4) + l; //correct

Page 8: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 8

Expression evaluation sequence

i = 0;while ( i < n){ y[i] = x[i++];}

There is no guarantee that address of y[i] will be evaluated before i is incremented.

Only operators &&, ||, ?:, and , specify an order of evaluation.

i = 0; // This workswhile (i < n){ y[i] = x[i]; ++i;}

Keep things simple and they will be reliable.

Expression order for function parameters.

Page 9: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 9

Shift operators

• In right shift are vacated bits filled with zeros or sign bit?

If item is unsigned zeros are filled in.

If item is signed, implementation is permitted to fill either zero, or sign bit.

Page 10: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 10

Shift operators

• What values are permitted for a shift count?

• For an n-bit number

Shift count >= 0

Shift count < n [strictly]

Otherwise result is undefined !

Page 11: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 11

Shift operators

• Is right shift same as divide by 2?

Well mostly yes.

For signed numbers sign bit should be copied in vacated bits.

But not Always!

Try this!

(-1)>>1

Page 12: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 12

Are Assignment statements expressions?

• Is the following statement valid?

a = b = c+d*e;

• Assignment statements are expressions as well. Expressions have operators, operands and a result.

The result (like operators and operands) do have a type and a value.

The value and type of an expression is the same as the type and value of the lhs of an expression.

• You must be familiar with the following code segments

if (a = (b+c)) ….

while (ch = getc()) ….

Page 13: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 13

Watch those semicolons!

struct { int x;}f(){ ...}

if (x[i] > big); big = x[i];

Don’t trust implicit return types.Be careful of semicolons.

Page 14: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 14

The switch statement

switch (color){ case 1: printf ("red"); case 2: printf("yellow"); break; case 3: printf("blue");}

Be careful of ‘break’. It is weakness as well as strength of ‘C’.

case SUBTRACT: opnd2 = -opnd2; /* falls through*/ case ADD: ...

Use comments if a case falls through into another.

Page 15: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 15

The dangling ‘else’

if (x == 0) if (y == 0) error();else{ z = x + y; f(&z);}

if (x == 0){ if (y == 0) { error(); }}else{ z = x + y; f(&z);}

Indentation is good as people understand it well.

Braces are necessary as compilers understand it well.

Page 16: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 16

Functions and Parameter Passing

• Functions are also types to the compilers

Type of a function comprises of the signature and the return type.

• Function names are identifiers.

• Parameters are passed in C using “call by value”.

This value may be an integer, an array, a structure or a pointer.

Page 17: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 17

Call by Value

• There is no mechanism called “call by address”.

The value passed may legitimately be an address and therefore the type of the formal parameter is pointer.

• The value of the actual parameter can never be changed from within a function invocation.

What we change at the most is what has been pointed to by a formal parameter.

Change in the formal parameter, in case the formal parameter is an address, can never be reflected in the value of the actual parameter.

Page 18: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 18

Array & Pointer• These are two separate data types. Array name is an

l-value that cannot be modified.

• Initialization of an array has a different syntax than initialization of a pointer.

• Distinguish between the two. char a[] = "string literal";

char *p = "string literal";

char *p = "hello, world!"; p[0] = 'H'; // This code may crash

• Pointer to an array int (*ap)[N]; /* N is a constant expression.

• Passing statically and dynamically allocated multi-dimensional array in functions.

Page 19: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 19

Passing 1-D Arrays to Functions

• Consider a 1-d array int a[10] has to be passed to a function. Which of the following functions have the correct declaration?

void f (int *x)

void f (int x[5])

void f (int x[10])

void f (int x[12])

Page 20: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 20

Passing 2-D Arrays to Functions

• Consider a 1-d array int a[10][20] has to be passed to a function. Which of the following functions have the correct declaration?

void f (int * *x)

void f (int *x[20])

void f (int (*x)[10])

void f (int (*x)[20])

void f (int x[10][20])

Page 21: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 21

Structure & Alignment• Structure is a type.

Only operators valid on a structure are: =, &, .

Two structures cannot be compared.

• sizeof of a structure is most often more than the individual sizeof of its members

struct example

{

char c;

int n;

}

size of example is not 1+4.

Due to word alignment

• Word alignment is important for efficient machine level data storage and retrieval.

Page 22: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 22

Structure & Alignment

• Padding for word alignment cannot be turned off in a universal manner

• Determining the byte offset of a field within a structure

ANSI C defines a offsetof() macro, which should be used if available; see <stddef.h>. If you don't have it, one possible implementation is

#define offsetof(type, mem) ((size_t) ((char *)&((type *)0)->mem - (char *)(type *)0))

This implementation is not 100% portable; some compilers may legitimately refuse to accept it.

Build a table of names and offsets, using the offsetof() macro. The offset of field b in struct a is

offsetb = offsetof(struct a, b)

If structp is a pointer to an instance of this structure, and field b is an int (with offset as computed above), b's value can be set indirectly with

*(int *)((char *)structp + offsetb) = value;

Page 23: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 23

NULL pointers

• It must never be dereferenced.

• The NULL pointer is not a null string.

if (p == (char *) 0) ... //ok

if (strcmp(p, (char *)0) == 0) ... //invalid

printf(p); //invalid if p is null pointer

Page 24: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 24

NULL pointer

• NULL pointer is a literal for every pointer type. However, the type of NULL is different in different contexts.

• NULL and NULL pointer are not the same. NULL is a macro that is defined to be 0.

• A constant 0 in a pointer context is converted into a null pointer at compile time. That is, in an initialization, assignment, or comparison when one side is a variable or an expression of pointer type, the compiler can tell that a constant 0 on the other side requests a null pointer, and generate the correctly-typed null pointer value. Therefore, the following fragments are perfectly legal char *p = 0; if(p != 0)

Page 25: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 25

NULL pointers in Functions

• An argument being passed to a function is not necessarily recognizable as a pointer context, and the compiler may not be able to tell that an unadorned 0 “means” a null pointer. To generate a null pointer in a function call context, an explicit cast may be required, to force the 0 to be recognized as a pointer.

• Suppose NULL is defined as follows:

#define NULL ((char *)0)

wouldn't that make function calls which pass an uncast NULL work?

Not in general.

Page 26: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 26

getchar() returns an integer

#include <stdio.h>int main(){ char c; while ((c = getchar()) != EOF) { putchar(c); }}

Catch the bug!!!

‘char c’ can’t hold EOF, use ‘int c’ instead.

Page 27: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 27

The preprocessor

• Important for following major reasons

We can change all instances of a particular quantity

For defining macros that appear to be functions, but do not have the function calling overhead

Page 28: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 28

Macros are not functions

• In a macro, an operand that is used twice may be evaluated twice.

• Expressions like x[i++] lead to side effects.

• Avoid side effects!

#define MAX(a,b) (((a) > (b)) ? (a) : (b))

biggest = x[0];i = 1;while (i < n) biggest = MAX(biggest, x[i++]); // wrong??

Page 29: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 29

Understanding Declarations

int *gi(); () binds more tightly than *.

*gi() is same as*(gi())

*(gi()) is of type int

=> gi() is a pointer to int,

=> gi is a function that returns pointer to int.

int (*hi)(); (*hi)() is int

=> (*hi) is a function that returns int

=> hi is a pointer to a function that returns int

Page 30: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 30

Understanding typecasts

If you know how to declare a type, it is easy to write a cast for that type.

Type Declaration Cast

Pointer to function that returns int int (*fp)() int (*)()

Pointer to function that returns nothing

void (*fp)() void (*)()

Page 31: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 31

Try it yourself

• There is a function “void f()”. Its address is stored at location “0x0” in memory. Write a C statement to execute this function by taking address from “0x0”.

• What is meant by the following declaration? int signal( int (*)(int), int);

Page 32: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 32

Function pointers

• Variables which point to the address of a function

• We can implement call-backs

• Complicated syntax

• Use it only when you need it!

Page 33: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 33

A “Generic Search” Problem

• Suppose that we have to search one item from a list (dynamic array) of such items. We do not know the type of the item when we write the code.

• Pseudo codefor (int i; i < n; i++) {

if (equal(a[i], k)

return i;

}

• Issues: What is the type of the array “a”, variable “k”?

If “a” is declared as “void *”, *(a+i) is not defined.

How can we manage to write “equal” function?back

Page 34: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 34

Solution to Generic Search Problem

• Solution to the first two issues: Formal parameter “a” is of type void *.

However actual parameter for “a” may be a pointer to a list of any thing (e.g., rectangle, employee etc.)

The caller of “generic_search” has to supply the size of the type that the actual parameter of “a” points to.

Formal parameter of “k” is of type void *.

The caller ensures that the actual parameter for “a” and “k” are the same.

for (i = 0; i < n; i++) {

equal ( (void *)((char*)a + i *size), k)

return i;

} back

Page 35: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 35

Using Function pointers

• “equal” function can not be written by the implementer of “generic_search”.

• “equal” function can be written by the designer and developer of types such as rectangle.

• The prototype for “equal”must be fixed and may be int XXX(void *, void *).

• The actual function XXX may be passed to the “generic_search” routine by the caller.

int generic_search( void* a, int n, void *k, int size, int (*fp)(void *, void *)) {

for (i = 0; i < n; i++) {

if ((*fp)( (void *)((char*)a + i *size), k) == 0)

return i;

}

}

Page 36: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 36

Check external types yourself

file1.c

extern int n;

file2.c

char n;

Compiler compiles single file, doesn’t know contents of others.

Linkers may not know about data types.

The program may work just by coincidence!!

Page 37: Slide: 1 CAMP 06: Maturing Minds Programming in C Recap Camp 06 Maturing Minds

CAMP 06: Maturing MindsSlide: 37

Reentrancy

• For the code to be re-entrant, each invocation must use its own copy of any modifiable data .

• Static variables should not be used.

• Global variables should not be used [except constants]

• Automatic variables should be used.

• No calls to a non-reentrant code should be made.