KEMBAR78
Advanced C programming | PPT
1
Advanced C Programming
Claus Wu
2
Agenda
 Pointer overview
 Precedence rule
 Assignments and pointers
 Arrays and pointers
 Pointers to functions
 Reference type
 Linking
 Cache
3
Pointer Types
 A pointer is a variable which contains the address in
memory of another variable.
 We can have a pointer to any variable type.
 The operator ‘&’ gives the address of a variable.
 The indirection or dereference operator * gives the
contents of an object pointed to by a pointer.
 When a pointer is declared it does not point
anywhere. You must set it to point somewhere before
you use it.
 int* pi;
 *pi = 100;// error!!
4
Pointer Types (Cont.)
 A pointer can’t hold a nonaddress value.
 int ival;
 pi = ival; // error: pi assigned int value of ival
 Nor can a pointer be initialized or assigned the
address value of an object of another type.
 double dval;
 double *pd = &dval;
 pi = pd; // both are compile-time error
 pi = &dval; // invalid assignment: int * <- double *
5
Pointer Types (Cont.)
int x = 1, y = 2;
int* ip;
ip = &x;
y = *ip;
x = ip;
*ip = 3;
1 2 100x y ip
100 200 1000
1 1 100x y ip
100 200 1000
100 1 100x y ip
100 200 1000
3 1 100x y ip
100 200 1000
6
void * Pointer
 The void* pointer can be assigned the address value
of any data pointer type.
 The void* indicates that the associated value is an
address but the type of the object at that address is
unknown.
 int *pi = 0;
 void *pv;
 pv = pi; // ok: implicit conversion
 pi = pv; // error: no standard conversion
 const int *pci = &ival;
 pv = pci; // error: pv isn’t a const void *
 const void *pcv = pci; // ok
7
Integer Arithmetic on a Pointer
 char* cp;
 float* flp;
 cp++; // add 1 byte to the address
 flp++; // add 4 bytes to the address
flp flp++ flp+2
4 bytes
8
Dereference Operator *
 Example
 int ival = 10;
 int* pi = &ival; // pi is a pointer to int
 int** ppi = &pi; // ppi is a pointer to a pointer to int
 int* pi2 = *ppi; // dereference ppi
 printf("ival=%dn*pi=%dn**ppi=%d", ival, *pi, **ppi);
 Results
 ival=10
 *pi=10
 **ppi=10
10
1200
1200
1232
1200
1232
1320
ival
pi
pii
pi2 1324
9
Precedence Rule
 What exactly, does the following declaration
declare?
 char* const * (*next)();
10
Precedence Rule
 . is higher than *
 *p.f -> *(p.f)
 Take the f offset from p, use it as a pointer
 [] is higher than *
 int *ap[] -> int *(ap[])
 ap is an array of ptrs-to-int
 Function () higher than *
 int *fp() -> int *(fp())
 fp is a function returning ptr-to-int
11
Precedence Rule (Cont.)
 == and != higher than bitwise operators
 val & mask !=0 -> val & (mask != 0)
 == and != higher than assignment
 c = getchar() != EOF -> c = (getchar() != EOF)
 Arithmetic higher precedence than shift
 msb << 4 + lsb -> msb << (4+lsb)
 , has lowest precedence of all operators
 i = 1, 2; -> (i = 1), 2;
12
Precedence Rule (Cont.)
 Declarations are read by starting with the name and
then reading in precedence order.
 The precedence, from high to low, is:
 parentheses grouping together parts of a declaration
 the posfix operators:

parentheses () indicating a function, and square brackets []
indicating an array.
 the prefix operator: the asterisk denoting "pointer to".
 If a const keyword is next to a type specifier (e.g. int,
long, etc.), it applies to the type specifier.
 Otherwise the const keyword applies to the pointer
asterisk on its immediate left.
13
Precedence Rule (Cont.)
 char* const * (*next)()
 next is a pointer to a function returning a pointer to
a const pointer-to-char
 Try to explain it
 char *(*c[10])(int **p);
14
Assignment and Qualifiers
Problems for Pointers
 Why it can’t work?
 void foo(const char **p) { }
 int main(int argc, char** argv)
 {
 foo(argv);
 }
 You will get: cannot convert parameter 1 from
'char **' to 'const char**'
15
Assignment and Qualifiers
Problems for Pointers (Cont.)
 Keyword const doesn’t turn a variable to a constant
 This makes the value read-only through that symbol.
 Rules
 Argument passing is supposed to behave like assignment.
 Both operands are pointers to qualified or unqualified
versions of compatible types, and the type pointed to by the
left has all the qualifiers of the type pointed to by the right.
16
Assignment and Qualifiers
Problems for Pointers (Cont.)
 Argument char *s matches parameter const
char *p.
 s: An unqualified pointer to a character with no
qualifiers.
 p: An unqualified pointer to a character qualified
by const qualifier.
 p = s, legal.
 s = p, illegal.
17
Assignment and Qualifiers
Problems for Pointers (Cont.)
 Argument char **s can’t match parameter
const char **p.
 s: A pointer to an unqualified pointer to a character with no
qualifiers.
 p: A pointer to an unqualified pointer to a character qualified
by const qualifier.
 Both s and p are pointers to unqualified types that aren’t the
same type – incompatible type
 Both s = p and p = s aren’t allowed.
p
s
const char
char
18
const Orderings
 Possible ordering for pointer and const
 const int * grape;
 int const * grape;
 int * const grape;

The first two make the object that it points at read-only.

The last one make pointer read-only.
19
const Orderings (Cont.)
 Example:
 const int a = 10;
 int b = 5;
 const int *pc; // pointer to const int
 int *const cp = &b; // const pointer to int
 pc = &a; // legal
 *pc = 5; // you cannot assign to a variable that is const
 pc = &b; // legal
 *cp = 0; // legal
 cp = &a; // cannot convert from 'const int *__w64' to 'int *const'
20
Symbol Overloading
 static
 Inside a function, retains its value between calls.
 At the function level, visible only in this file.
 extern
 Applied to a function definition, has global scope.
 Applied to a variable, defined elsewhere.
21
Symbol Overloading (Cont.)
 void
 At the return type of a function, doesn’t return a
value.
 In a pointer declaration, the type of generic
pointer.
 In a parameter list, takes no parameters.
 *
 The multiplication operator.
 Applied to a pointer, indirection.
 In a declaration, a pointer.
22
Rule for Return Type
 A function can’t return a function.
 You never see foo()().
 A function can’t return an array.
 You never see foo()[].
 A array can’t hold a function.
 You never see foo[]().
23
Rule for Return Type (Cont.)
 A function returning a pointer to a function is
allowed: int (* fun())()
 A function returning a pointer to an array is
allowed: int (* foo())[]
 An array holding pointers to function is
allowed: int (* foo[])()
 An array can hold other array, so you
frequently see: int foo[][]
24
typedef
 Simplify declaration
 Example:
 Declaration for signal

void (*signal(int sig, void (*func)(int)))(int);
 Using typedef

void (*signal( ))(int);
 signal is a function returning a pointer to a function.

typedef void (*ptr_to_func)(int);
 A pointer to a function taking an int argument and returning void.
 Simlified version of signal

ptr_to_func signal(int, ptr_to_func);
25
Differences between typedef
and #define
 You can extend a macro typename with other
type identifier
 #define peach int
 unsigned peach i; /* work fine */
 typedef int banana;
 unsigned banana i; /* illegal */
26
Differences between typedef
and #define (Cont.)
 A typedef’d name provides the type for every
declarator in a declaration
 typedef char * char_ptr;
 char_ptr a, b;
 #define int_ptr int *
 int_ptr c, d;

It becomes int *c, d;
27
Definition vs. Declaration
 Definition
 occurs only one place
 specifies the type of an object; reserves storage
for it; is used to create new objects
 ex. int my_array[100];
 Declaration
 can occur multiple times
 describe the type of an object; is used to refer to
objects defined elsewhere
 ex. extern int my_array[];
28
Match Your Declarations to
the Definition
 Why doesn’t it work?
 File 1:

int mango[100];
 File 2:

extern int *mango;
 some code that reference mango[i]
 Change declaration to match definition
 File 1:

int mango[100];
 File 2:
 extern int mango[];
29
A Subscripted Array
Reference
 char a[9] = “abcdefgh”;
 c = a[i];
Compiler symbol table has a as address 9980
Runtime step 1: get value i, and add it to 9980
Runtime step 2: get the contents from address (9980+i)
9980 +1 +i+2
30
A Subscripted Pointer
Reference
 char *p = “abcdefgh”;
 c = p[i];
Compiler symbol table has p as address 4624
Runtime step 1: get the contents from address 4624, say 5081
Runtime step 2: get value i, and add it to 5081
Runtime step 3: get the contents from address (5081+i)
5081 +1 +i+2
50814624
(5081+i)
31
When Arrays Are Pointers
 Rule 1: An array name in an expression is a
pointer.
 An array reference a[i] is always rewritten to *(a+i)
by the compiler.
 a[i] can can be accessed in any of these ways:

p=a; p[i];

p=a; *(p+i);

p=a+i; *p;
32
When Arrays Are
Pointers(Cont.)
 Rule 2: C treats array subscripts as pointer
offsets.
 Rule 3: Array name as a function parameter
is a pointer.
 They are all completely equivalent:

my_func(int* turnip) {}

my_func(int turnip[]) {}

my_func(int turnip[100]) {}
33
When You See squash[i][j] – You
Don’t Known How It Was Declared!
 int squash[5][10];
 array[5] of array[10] of int
 int *squash[5];

an array of 5 pointers-to-int
 int **squash;
 pointer to a pointer to int
 int (*squash)[10];
 pointer to array-of-10-ints
34
A Pointers to Pointers
Example
 Consider the following:
 char ch; /* a character */
 char *pch; /* a pointer to a character */
 char **ppch; /* a pointer to a pointer to a character */
ppch pch ch
string
ppch pch
string0
ppch
pch
0
string1
string2
Pointers to pointers
Pointers to string
Pointers to several strings,
is identical to *ppch[].
35
Multidimension
 int apricot[2][3][5] = {0};
 apricot[1][2][2] = 1; // 1 * (3*5) + 2*5 + 2 = 27
 int *r = apricot[1][2]; // 1 * (3*5) + 2*5
 r[2] = 5; // + 2 = 27
 int (*s)[5] = apricot[1]; // 1 * (3*5)
 s[2][2] = 2; // + 2*5 + 2 = 27
 int (*t)[3][5] = apricot; // 0
 t[1][2][2] = 4; // + 1 * (3*5) + 2*5 + 2 = 27
apricot[1][2][2]
*r(*s)[5]
(*t)[3][5]
apricot
36
Pointers to Functions
 Declaration
 int (*pf)(char*, char*)
 pf to be a pointer to a function that takes two parameters
and has a return type of int.
 Assignment
 int calc(int, int);
 int (*pf2i)(int, int) = 0;
 int (*pf2s)(char*, char*) = 0;
 pf2i = calc; // ok
 pf2s = calc; // type mismatch
37
Pointers to Functions (Cont.)
 Invocation
 pf2i(x, y);
 (*pf2i)(x, y); // the same as above, but more readable
 A pointer to a function can be the type of a function’s
return value:
 int (*ff(int))(int, int);
 It declared ff() to be a function taking one parameter of type
int, return a pointer to a function type int (*)(int, int).
 Use typedef to make it easier to read:

typedef int (*PF)(int, int);

PF ff(int);
38
Pointers to extern “C”
Function
 A pointer pf refers to a C function in a cpp file:
 extern “C” void exit(int); // a C function
 extern “C” void (*pf)(int) = exit;
 A pointer to a C function can’t be initialized or be
assigned to a pointer to a C++ function (and vice
versa)
 void (*pf1)(int);
 extern “C” void (*pf2)(int);
 pf1 = pf2;// error: pf1 and pf2 have different types
39
Pointers to extern “C”
Function (Cont.)
 When a linkage directive applies to a declaration, all
functions declared by the declaration are affected by
the linkage directive
 // pfParm is a pointer to a C function
 extern “C” void f1(void (*pfParm)(int));
 Use typedef to make a C++ function to have a
parameter that is a pointer to a C function
 extern “C” typedef void FC(int);
 // f2() is a C++ function with a parameter that is
 // a pointer to a C function
 void f2(FC* pfParm);
40
Arrays of Pointers to Function
 int (*pfv[10])()
 Declares pfv to be array of ten elements. Each element is a
pointer to a function that take no arguments and that has a
return type of int
 Use typedef to simplify declaration:
 typedef int (*PFV)();
 PFV pfv[10];
 Invocation
 int ret = pfv[0]();
41
Arrays of Pointers to Function
(Cont.)
 An array of pointers to functions can be initialized
using initializer list in which each initializer represents
a function of the same type as the type of the array
element
 int lexicoCompare(char *, char *);
 int sizeCompare(char *, char *);
 typedef int (*PFS)(char *, char *);
 PFS compareFunc[2] = {lexicoCompare, sizeCompare};
42
Reference Type
 Once defined, a reference can’t be made to refer to
another object.
 A reference serves as a kind of pointer
 int val = 10;
 int &refVal = &val; // error: refVal is of type int, not int*
 int* pi = &val;
 int *&refPtr = pi; // refPtr is a reference to a pointer
 Swap two pointers
 void ptrSwap(int *&v1, int *&v2) {
 int* tmp = v2
 v2 = v1
 v1 = tmp;
 }
43
Array Parameters
 The size of an array isn’t part of its parameter type:
 void putValues(int [10]); // equal to putValues(int *)
 int i, j[2];
 putValues(&i); // ok, but potential run-time error
 putValues(j); // ok, but potential run-time error
 When the parameter is a reference of an array type,
the array size become part of the parameter:
 void putValues(int (&ar)[10]);

parameter is a reference to an array of 10 ints
 int i, j[2];
 putValues(&i); // error, i is not an array of 10 ints
 putValues(j); // error, j is not an array of 10 ints
44
Header File
 Never contain a definition, for example:
 extern int ival=10;

The declaration of a global object specifies both extern and
explicit initializer is treated as a definition
 double rate;

No extern keyword, so it is a definition
 extern void dummy() { }

The empty brace pair stands as the definition of that function
 Symbolic constants and inline functions can be
defined many times, so they don’t violate this rule
 Their definitions can appear in a header file
45
Linkage Directives: extern “C”
 Indicate to the compiler that a function is
written in a different programming language.
 extern “C” void exit(int);
 A linkage directive can’t appear within a
function.
46
Static Linking versus Dynamic
Linking
hello.chello.c
libc.alibc.a
libc.solibc.so
a.outa.out
a.outa.outresult in
result in
statically linked with
dynamically linked with Library functions are mapped
into the process at runtime
1KB
750KB
620KB
502KB
5KB
47
BSS
 BSS – Block Started by Symbol.
 Only hold variables that don’t have any value
yet.
 It doesn’t actually need to store the image of
these variables.
 The size of that BSS will require at runtime is
recorded in the object file.
48
Executable File Format
char pear[40];
static double peach;
int mango = 13;
static long melon = 2001;
main()
{
int i = 3, j, *ip;
ip = malloc(sizeof(i));
pear[5] = i;
peach = 2.0 * mango;
/* other codes */
a.out magic number
other a.out contents
size need for BSS segment
data segment
initialized global and
static variables
text segment
executable instructions
Source file a.out file
Local variables don’t go in a.out,
but are created at runtime.
49
How a.out Maps to Memory?
a.out magic number
other a.out contents
size need for BSS segment
data segment
initialized global and
static variables
text segment
executable instructions
a.out file
data segment
text segment
BSS segment
stack segment
the hole
Address space of a process
highest memory address
unmapped
lowest memory address
(instructions)
(initialized
data)
(uninitialized
data)
(data local
to functions)
50
Stack Segment
 The stack provides the storage area for local
variables declared inside functions
 The stack stores the "housekeeping" information
involved when a function call is made
 a procedure activation record
 any parameters that won't fit into registers
 saved values of registers
 The stack also works as a scratch-pad area — every
time the program needs some temporary storage
 To evaluate a lengthy arithmetic expression, it can push
partial results onto the stack, popping them when needed.
 Storage obtained by the alloca() call is also on the stack.
51
Data Segment & Heap
data segment
text segment
stack segment
the hole
unmapped
lowest memory address
(data local
to functions)
the heap
the break
used for malloc()
BSS segment
highest memory address
52
Data Segment & Heap (Cont.)
 Heap
 Make data segment grows dynamically on
demand.
 Storage is obtained through malloc and accessed
through a pointer.
 The end of the heap is marked by a pointer known
as the break.
 Heap management
 malloc and free – get memory from heap and give
it back to heap.
 brk and sbrk – adjust the size of the data segment.
53
Considering the Cache
 Why SMARTCOPY is faster?
#define DUMBCOPY for (int i = 0; i < 65536; i++) 
destination[i] = source[i]
#define SMARTCOPY memcpy(destination, source, 65536)
main()
{
char source[65536], destination[65536];
for (int j = 0; j < 100; j++)
DUMBCOPY;
for (int j = 0; j < 100; j++)
SMARTCOPY;
}
54
Memory Organization
CPU
Cache
Memory
Bus
55
32-Bit Processor Memory
Organization
56
A Better Example of Memcpy
void* Memcpy(void* dst, void const* src, size_t len)
{
long* plDst = (long *)dst;
long const* plSrc = (long const *)src;
if (0xFFFFFFFC & len) {
while (len >= 4) {
*plDst++ = *plSrc++; // copy 4 bytes every time
len -= 4;
}
}
// copy remainder bytes
char* pcDst = (char *)plDst;
char const* pcSrc = (char const *)plSrc;
while (len--)
*pcDst++ = *pcSrc++; // copy 1 byte every time
return dst;
}
57
References
 Expert C Programming - Deep C Secrets, by
Peter van der Linden
 Programming in C,
http://www.cs.cf.ac.uk/Dave/C/CE.html
 C++ Primer, 3rd Edition, by Stanley B.
Lippman & Josee Lajoie

Advanced C programming

  • 1.
  • 2.
    2 Agenda  Pointer overview Precedence rule  Assignments and pointers  Arrays and pointers  Pointers to functions  Reference type  Linking  Cache
  • 3.
    3 Pointer Types  Apointer is a variable which contains the address in memory of another variable.  We can have a pointer to any variable type.  The operator ‘&’ gives the address of a variable.  The indirection or dereference operator * gives the contents of an object pointed to by a pointer.  When a pointer is declared it does not point anywhere. You must set it to point somewhere before you use it.  int* pi;  *pi = 100;// error!!
  • 4.
    4 Pointer Types (Cont.) A pointer can’t hold a nonaddress value.  int ival;  pi = ival; // error: pi assigned int value of ival  Nor can a pointer be initialized or assigned the address value of an object of another type.  double dval;  double *pd = &dval;  pi = pd; // both are compile-time error  pi = &dval; // invalid assignment: int * <- double *
  • 5.
    5 Pointer Types (Cont.) intx = 1, y = 2; int* ip; ip = &x; y = *ip; x = ip; *ip = 3; 1 2 100x y ip 100 200 1000 1 1 100x y ip 100 200 1000 100 1 100x y ip 100 200 1000 3 1 100x y ip 100 200 1000
  • 6.
    6 void * Pointer The void* pointer can be assigned the address value of any data pointer type.  The void* indicates that the associated value is an address but the type of the object at that address is unknown.  int *pi = 0;  void *pv;  pv = pi; // ok: implicit conversion  pi = pv; // error: no standard conversion  const int *pci = &ival;  pv = pci; // error: pv isn’t a const void *  const void *pcv = pci; // ok
  • 7.
    7 Integer Arithmetic ona Pointer  char* cp;  float* flp;  cp++; // add 1 byte to the address  flp++; // add 4 bytes to the address flp flp++ flp+2 4 bytes
  • 8.
    8 Dereference Operator * Example  int ival = 10;  int* pi = &ival; // pi is a pointer to int  int** ppi = &pi; // ppi is a pointer to a pointer to int  int* pi2 = *ppi; // dereference ppi  printf("ival=%dn*pi=%dn**ppi=%d", ival, *pi, **ppi);  Results  ival=10  *pi=10  **ppi=10 10 1200 1200 1232 1200 1232 1320 ival pi pii pi2 1324
  • 9.
    9 Precedence Rule  Whatexactly, does the following declaration declare?  char* const * (*next)();
  • 10.
    10 Precedence Rule  .is higher than *  *p.f -> *(p.f)  Take the f offset from p, use it as a pointer  [] is higher than *  int *ap[] -> int *(ap[])  ap is an array of ptrs-to-int  Function () higher than *  int *fp() -> int *(fp())  fp is a function returning ptr-to-int
  • 11.
    11 Precedence Rule (Cont.) == and != higher than bitwise operators  val & mask !=0 -> val & (mask != 0)  == and != higher than assignment  c = getchar() != EOF -> c = (getchar() != EOF)  Arithmetic higher precedence than shift  msb << 4 + lsb -> msb << (4+lsb)  , has lowest precedence of all operators  i = 1, 2; -> (i = 1), 2;
  • 12.
    12 Precedence Rule (Cont.) Declarations are read by starting with the name and then reading in precedence order.  The precedence, from high to low, is:  parentheses grouping together parts of a declaration  the posfix operators:  parentheses () indicating a function, and square brackets [] indicating an array.  the prefix operator: the asterisk denoting "pointer to".  If a const keyword is next to a type specifier (e.g. int, long, etc.), it applies to the type specifier.  Otherwise the const keyword applies to the pointer asterisk on its immediate left.
  • 13.
    13 Precedence Rule (Cont.) char* const * (*next)()  next is a pointer to a function returning a pointer to a const pointer-to-char  Try to explain it  char *(*c[10])(int **p);
  • 14.
    14 Assignment and Qualifiers Problemsfor Pointers  Why it can’t work?  void foo(const char **p) { }  int main(int argc, char** argv)  {  foo(argv);  }  You will get: cannot convert parameter 1 from 'char **' to 'const char**'
  • 15.
    15 Assignment and Qualifiers Problemsfor Pointers (Cont.)  Keyword const doesn’t turn a variable to a constant  This makes the value read-only through that symbol.  Rules  Argument passing is supposed to behave like assignment.  Both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right.
  • 16.
    16 Assignment and Qualifiers Problemsfor Pointers (Cont.)  Argument char *s matches parameter const char *p.  s: An unqualified pointer to a character with no qualifiers.  p: An unqualified pointer to a character qualified by const qualifier.  p = s, legal.  s = p, illegal.
  • 17.
    17 Assignment and Qualifiers Problemsfor Pointers (Cont.)  Argument char **s can’t match parameter const char **p.  s: A pointer to an unqualified pointer to a character with no qualifiers.  p: A pointer to an unqualified pointer to a character qualified by const qualifier.  Both s and p are pointers to unqualified types that aren’t the same type – incompatible type  Both s = p and p = s aren’t allowed. p s const char char
  • 18.
    18 const Orderings  Possibleordering for pointer and const  const int * grape;  int const * grape;  int * const grape;  The first two make the object that it points at read-only.  The last one make pointer read-only.
  • 19.
    19 const Orderings (Cont.) Example:  const int a = 10;  int b = 5;  const int *pc; // pointer to const int  int *const cp = &b; // const pointer to int  pc = &a; // legal  *pc = 5; // you cannot assign to a variable that is const  pc = &b; // legal  *cp = 0; // legal  cp = &a; // cannot convert from 'const int *__w64' to 'int *const'
  • 20.
    20 Symbol Overloading  static Inside a function, retains its value between calls.  At the function level, visible only in this file.  extern  Applied to a function definition, has global scope.  Applied to a variable, defined elsewhere.
  • 21.
    21 Symbol Overloading (Cont.) void  At the return type of a function, doesn’t return a value.  In a pointer declaration, the type of generic pointer.  In a parameter list, takes no parameters.  *  The multiplication operator.  Applied to a pointer, indirection.  In a declaration, a pointer.
  • 22.
    22 Rule for ReturnType  A function can’t return a function.  You never see foo()().  A function can’t return an array.  You never see foo()[].  A array can’t hold a function.  You never see foo[]().
  • 23.
    23 Rule for ReturnType (Cont.)  A function returning a pointer to a function is allowed: int (* fun())()  A function returning a pointer to an array is allowed: int (* foo())[]  An array holding pointers to function is allowed: int (* foo[])()  An array can hold other array, so you frequently see: int foo[][]
  • 24.
    24 typedef  Simplify declaration Example:  Declaration for signal  void (*signal(int sig, void (*func)(int)))(int);  Using typedef  void (*signal( ))(int);  signal is a function returning a pointer to a function.  typedef void (*ptr_to_func)(int);  A pointer to a function taking an int argument and returning void.  Simlified version of signal  ptr_to_func signal(int, ptr_to_func);
  • 25.
    25 Differences between typedef and#define  You can extend a macro typename with other type identifier  #define peach int  unsigned peach i; /* work fine */  typedef int banana;  unsigned banana i; /* illegal */
  • 26.
    26 Differences between typedef and#define (Cont.)  A typedef’d name provides the type for every declarator in a declaration  typedef char * char_ptr;  char_ptr a, b;  #define int_ptr int *  int_ptr c, d;  It becomes int *c, d;
  • 27.
    27 Definition vs. Declaration Definition  occurs only one place  specifies the type of an object; reserves storage for it; is used to create new objects  ex. int my_array[100];  Declaration  can occur multiple times  describe the type of an object; is used to refer to objects defined elsewhere  ex. extern int my_array[];
  • 28.
    28 Match Your Declarationsto the Definition  Why doesn’t it work?  File 1:  int mango[100];  File 2:  extern int *mango;  some code that reference mango[i]  Change declaration to match definition  File 1:  int mango[100];  File 2:  extern int mango[];
  • 29.
    29 A Subscripted Array Reference char a[9] = “abcdefgh”;  c = a[i]; Compiler symbol table has a as address 9980 Runtime step 1: get value i, and add it to 9980 Runtime step 2: get the contents from address (9980+i) 9980 +1 +i+2
  • 30.
    30 A Subscripted Pointer Reference char *p = “abcdefgh”;  c = p[i]; Compiler symbol table has p as address 4624 Runtime step 1: get the contents from address 4624, say 5081 Runtime step 2: get value i, and add it to 5081 Runtime step 3: get the contents from address (5081+i) 5081 +1 +i+2 50814624 (5081+i)
  • 31.
    31 When Arrays ArePointers  Rule 1: An array name in an expression is a pointer.  An array reference a[i] is always rewritten to *(a+i) by the compiler.  a[i] can can be accessed in any of these ways:  p=a; p[i];  p=a; *(p+i);  p=a+i; *p;
  • 32.
    32 When Arrays Are Pointers(Cont.) Rule 2: C treats array subscripts as pointer offsets.  Rule 3: Array name as a function parameter is a pointer.  They are all completely equivalent:  my_func(int* turnip) {}  my_func(int turnip[]) {}  my_func(int turnip[100]) {}
  • 33.
    33 When You Seesquash[i][j] – You Don’t Known How It Was Declared!  int squash[5][10];  array[5] of array[10] of int  int *squash[5];  an array of 5 pointers-to-int  int **squash;  pointer to a pointer to int  int (*squash)[10];  pointer to array-of-10-ints
  • 34.
    34 A Pointers toPointers Example  Consider the following:  char ch; /* a character */  char *pch; /* a pointer to a character */  char **ppch; /* a pointer to a pointer to a character */ ppch pch ch string ppch pch string0 ppch pch 0 string1 string2 Pointers to pointers Pointers to string Pointers to several strings, is identical to *ppch[].
  • 35.
    35 Multidimension  int apricot[2][3][5]= {0};  apricot[1][2][2] = 1; // 1 * (3*5) + 2*5 + 2 = 27  int *r = apricot[1][2]; // 1 * (3*5) + 2*5  r[2] = 5; // + 2 = 27  int (*s)[5] = apricot[1]; // 1 * (3*5)  s[2][2] = 2; // + 2*5 + 2 = 27  int (*t)[3][5] = apricot; // 0  t[1][2][2] = 4; // + 1 * (3*5) + 2*5 + 2 = 27 apricot[1][2][2] *r(*s)[5] (*t)[3][5] apricot
  • 36.
    36 Pointers to Functions Declaration  int (*pf)(char*, char*)  pf to be a pointer to a function that takes two parameters and has a return type of int.  Assignment  int calc(int, int);  int (*pf2i)(int, int) = 0;  int (*pf2s)(char*, char*) = 0;  pf2i = calc; // ok  pf2s = calc; // type mismatch
  • 37.
    37 Pointers to Functions(Cont.)  Invocation  pf2i(x, y);  (*pf2i)(x, y); // the same as above, but more readable  A pointer to a function can be the type of a function’s return value:  int (*ff(int))(int, int);  It declared ff() to be a function taking one parameter of type int, return a pointer to a function type int (*)(int, int).  Use typedef to make it easier to read:  typedef int (*PF)(int, int);  PF ff(int);
  • 38.
    38 Pointers to extern“C” Function  A pointer pf refers to a C function in a cpp file:  extern “C” void exit(int); // a C function  extern “C” void (*pf)(int) = exit;  A pointer to a C function can’t be initialized or be assigned to a pointer to a C++ function (and vice versa)  void (*pf1)(int);  extern “C” void (*pf2)(int);  pf1 = pf2;// error: pf1 and pf2 have different types
  • 39.
    39 Pointers to extern“C” Function (Cont.)  When a linkage directive applies to a declaration, all functions declared by the declaration are affected by the linkage directive  // pfParm is a pointer to a C function  extern “C” void f1(void (*pfParm)(int));  Use typedef to make a C++ function to have a parameter that is a pointer to a C function  extern “C” typedef void FC(int);  // f2() is a C++ function with a parameter that is  // a pointer to a C function  void f2(FC* pfParm);
  • 40.
    40 Arrays of Pointersto Function  int (*pfv[10])()  Declares pfv to be array of ten elements. Each element is a pointer to a function that take no arguments and that has a return type of int  Use typedef to simplify declaration:  typedef int (*PFV)();  PFV pfv[10];  Invocation  int ret = pfv[0]();
  • 41.
    41 Arrays of Pointersto Function (Cont.)  An array of pointers to functions can be initialized using initializer list in which each initializer represents a function of the same type as the type of the array element  int lexicoCompare(char *, char *);  int sizeCompare(char *, char *);  typedef int (*PFS)(char *, char *);  PFS compareFunc[2] = {lexicoCompare, sizeCompare};
  • 42.
    42 Reference Type  Oncedefined, a reference can’t be made to refer to another object.  A reference serves as a kind of pointer  int val = 10;  int &refVal = &val; // error: refVal is of type int, not int*  int* pi = &val;  int *&refPtr = pi; // refPtr is a reference to a pointer  Swap two pointers  void ptrSwap(int *&v1, int *&v2) {  int* tmp = v2  v2 = v1  v1 = tmp;  }
  • 43.
    43 Array Parameters  Thesize of an array isn’t part of its parameter type:  void putValues(int [10]); // equal to putValues(int *)  int i, j[2];  putValues(&i); // ok, but potential run-time error  putValues(j); // ok, but potential run-time error  When the parameter is a reference of an array type, the array size become part of the parameter:  void putValues(int (&ar)[10]);  parameter is a reference to an array of 10 ints  int i, j[2];  putValues(&i); // error, i is not an array of 10 ints  putValues(j); // error, j is not an array of 10 ints
  • 44.
    44 Header File  Nevercontain a definition, for example:  extern int ival=10;  The declaration of a global object specifies both extern and explicit initializer is treated as a definition  double rate;  No extern keyword, so it is a definition  extern void dummy() { }  The empty brace pair stands as the definition of that function  Symbolic constants and inline functions can be defined many times, so they don’t violate this rule  Their definitions can appear in a header file
  • 45.
    45 Linkage Directives: extern“C”  Indicate to the compiler that a function is written in a different programming language.  extern “C” void exit(int);  A linkage directive can’t appear within a function.
  • 46.
    46 Static Linking versusDynamic Linking hello.chello.c libc.alibc.a libc.solibc.so a.outa.out a.outa.outresult in result in statically linked with dynamically linked with Library functions are mapped into the process at runtime 1KB 750KB 620KB 502KB 5KB
  • 47.
    47 BSS  BSS –Block Started by Symbol.  Only hold variables that don’t have any value yet.  It doesn’t actually need to store the image of these variables.  The size of that BSS will require at runtime is recorded in the object file.
  • 48.
    48 Executable File Format charpear[40]; static double peach; int mango = 13; static long melon = 2001; main() { int i = 3, j, *ip; ip = malloc(sizeof(i)); pear[5] = i; peach = 2.0 * mango; /* other codes */ a.out magic number other a.out contents size need for BSS segment data segment initialized global and static variables text segment executable instructions Source file a.out file Local variables don’t go in a.out, but are created at runtime.
  • 49.
    49 How a.out Mapsto Memory? a.out magic number other a.out contents size need for BSS segment data segment initialized global and static variables text segment executable instructions a.out file data segment text segment BSS segment stack segment the hole Address space of a process highest memory address unmapped lowest memory address (instructions) (initialized data) (uninitialized data) (data local to functions)
  • 50.
    50 Stack Segment  Thestack provides the storage area for local variables declared inside functions  The stack stores the "housekeeping" information involved when a function call is made  a procedure activation record  any parameters that won't fit into registers  saved values of registers  The stack also works as a scratch-pad area — every time the program needs some temporary storage  To evaluate a lengthy arithmetic expression, it can push partial results onto the stack, popping them when needed.  Storage obtained by the alloca() call is also on the stack.
  • 51.
    51 Data Segment &Heap data segment text segment stack segment the hole unmapped lowest memory address (data local to functions) the heap the break used for malloc() BSS segment highest memory address
  • 52.
    52 Data Segment &Heap (Cont.)  Heap  Make data segment grows dynamically on demand.  Storage is obtained through malloc and accessed through a pointer.  The end of the heap is marked by a pointer known as the break.  Heap management  malloc and free – get memory from heap and give it back to heap.  brk and sbrk – adjust the size of the data segment.
  • 53.
    53 Considering the Cache Why SMARTCOPY is faster? #define DUMBCOPY for (int i = 0; i < 65536; i++) destination[i] = source[i] #define SMARTCOPY memcpy(destination, source, 65536) main() { char source[65536], destination[65536]; for (int j = 0; j < 100; j++) DUMBCOPY; for (int j = 0; j < 100; j++) SMARTCOPY; }
  • 54.
  • 55.
  • 56.
    56 A Better Exampleof Memcpy void* Memcpy(void* dst, void const* src, size_t len) { long* plDst = (long *)dst; long const* plSrc = (long const *)src; if (0xFFFFFFFC & len) { while (len >= 4) { *plDst++ = *plSrc++; // copy 4 bytes every time len -= 4; } } // copy remainder bytes char* pcDst = (char *)plDst; char const* pcSrc = (char const *)plSrc; while (len--) *pcDst++ = *pcSrc++; // copy 1 byte every time return dst; }
  • 57.
    57 References  Expert CProgramming - Deep C Secrets, by Peter van der Linden  Programming in C, http://www.cs.cf.ac.uk/Dave/C/CE.html  C++ Primer, 3rd Edition, by Stanley B. Lippman & Josee Lajoie