Kernighan, Brian W. The C programming language

Chapter 1

1.1 Getting Started

A C program contains functions and variables

Chapter 5

pointer → address of a variable

additional

void * replaces char * as proper type for generic pointer.

5.1 Pointers and Addresses

typical machine has array of consecutively numbered memory cells managed individually or in contiguous groups.

char → byte

short → 2 bytes

long → 4 bytes

pointer is a group of cells (often 2 or 4) can hold an address.

unary operator & gives address of object

p = &c ;   // assign address of c to the variable p

& only applies to objects in memory: variables and array elements. (not for exp, const, reg var)

‘*’ indirection (dereferencing operator) when applied to pointer gets value of object pointer points to.

int x = 1, y =2 , z[10];
int *ip; // pointer to int 
ip = &x; // p points to x
y = *ip; // y is 1 ;
*ip = 0; //x ix 0;
ip = &z[0]; //ip points to z[0]
int *ip (as mneomonic )

//mimics syntax expression where variable might appear.

pointer points to a particular kind of object. (exception *void)

*ip can be used anywhere x is used.

//increment
*ip +=1
++*ip
(*ip)++ // or else increments the pointer itself
iq = ip // iq points to what ip is pointing at

5.2 Pointer and Function Arguments

Since c arguments to function by value no direct way functions to alter a variable.

void swap (int x, int y)
{
	int temp;
	temp = x ;
	x = y;
	y = temp;
}

WRONG!! as only updates copies of variables inside the function.  

Way to get desired functionality —> pointers.

swap(&a,&b);
void swap(int *px, int *py){
	int temp;
	temp = *px;
	*px = *py;
	*py = temp;
}

image

5.3 Pointers and Arrays

Any operation by array subscripting can be done by pointers. Pointer version faster but harder.

int a[10];
// a[i] refers to the ith elemtn of the array 

define array of size 10

image

int *pa;
pa = &a[0];
// pa points to zero element of a 

image

x = *pa 
//cp contents of a[0] into x

if pa is particular element of array pa+1 next pa-1 prev.

*(pa+1) 
//refers to a[1]

(pa+i)
//address of a[i]

*(pa+i)
//refers contents of a[i]

image

True regardless of type and size of variables in a. Correspondance between indexing and pointer arithmetic is very close. By definition value of variable of type array is the address of element at 0 .

Hence

pa = &a[0];
// pa and a have same value. 
// can also be written as
pa = a;

//More suprisingly a[i] can also be evaluated as 
*(a+i)
// while evaluating a[i] --> *(a+i)

&a[i] --> (a+i)

in short array and index expression equivalent to pointer and offset.

One difference to keep in mind pointer is a variable,

pa = a;
pa++;
//LEGAL

a = pa;
a++;
//ILLEGAL

but array is not.

When array name passed to function actually initial element is passed. Within called function the argument is a local variable so array name parameter is a pointer( variable ).

//strlen 
int strlen(char *s){
	int n;
	for (n=0;*s!='\0',s++)
		n++;
	return n;
} 

s++ perfectly legal. increments private copy pointer.

// Valid calls
strlen("Hello");
strlen(array); // char array[100];
strlen(ptr); // char *ptr;

As formal parameters in function definition

char s[]; === char * s;

but latter preferred, says more explicitly that variable is a pointer.

Possible to pass part of array

f(&a[2])
or
f(a+2)

//when reading parameters
f(int arr[]){...}
or 
f(int *arr){...}

if known can refer to preceding elements p[-1],p[-2]

ILLEGAL to refer to objects not within array bounds.

5.4 Address Arithmetic

Simplest forms of pointer arithmetic

p++ next object pointer

C has consistent and regular approach to address arithmetic. Two routines,

  • alloc(n) → returns pointer to n consecutive character positions.
  • afree(p) → release storage

the storages managed is a stack.

<stdlib.h> provides malloc and free with no such restrictions.

Chapter 6

Collection of one or more variables grouped together under a single name. Relatable data as a unit.

Example of a payroll employee with

  • name
  • address
  • ssn
  • salary

6.1 Basics of Structures

Point on x - y plane

struct point {
	int x;
	int y;
}

struct tag → point

variables in struct → members

struct tag and variable can have same name without conflict(distinguished by context). Same member name in different structures also possible.

struct declaration defines a type

struct {...} x,y,z;

analogous to,

int x,y,z;

Initializations

struct point pt;
struct maxpt = {320,200};

structure-name.member to reffer to member

printf("%d , %d",p.x,p.y);

Structure can be nested, for a rectangle on the 2D plane

image

struct rect {
	struct point pt1;
	struct point pt2;
}

to declare and access a rectangle as screen

struct rect screen;
screen.pt1.x;

6.2 Structures and Functions

Only legal operations on a structure are copying it or assigning to it as a unit. Taking address with & to access members. Structures may not be compared , automatic structure initialized by an assignment. Three ways to manipulate structures,

  • Pass components separately.
  • Pass entire structure
  • Pass a pointer to it
struct point makepoint(int x, int y){

	struct point temp;
	temp.x = x;
	temp.y = y;
	return temp;

}

Function can now be used as,

struct rect screen;
struct point middle;
struct point makepoint(int,int);

screen.pt1 = makepoint(0,0);
screen.pt2 = makepoint(XMAX, YMAX);
middle = makepoint((screen.pt1.x + screen.pt2.x)/2), (screen.pt1.y + scree.pt2.y)/2);

Arithmetic on the members

struct addpoint(struct point p1, struct point p2){
	p1.x += p2.x;
	p1.y += p2.y;
	return p1;
}

If a large structure is to be passed to a fucntion generally efficient to pass a pointer than to copy the whole thing. Structure pointers are same as ordinary pointers.

struct point *pp;

If pp points to a point structure, (pp).x and (*pp).y are members.

struct point origin, *pp;
pp = &origin;
printf("origin is (%d,%d)\n", (*pp).x,(*pp).y);

Pointers to structures are frequently used hence alternative notation , If p is a pointer to a structure then

// p-> member-of-structure
printf("origin is (%d %d) \n", pp->x, pp->y);

This shows

struct rect r, *rp = &r;
//Equivalent statements

r.pt1.x
rp-> pt1.x
(r.pt1).x
(rp->pt1).x

++p->len

//implies ++(p->len) increment of len not p

(++p)->len 
//increment p after accessing len

6.3 Arrays of Structures

Considering program to count occurrences of each C keyword need array of character strings to hold t he names and array to hold the count for each. A solution would be to keep two seperate arrays.

char * keyword[NKEYS];
int keycount[NKEYS];

This suggests a different organization array of structures where for each keyword is a pair as

char * word;
int count;

Hence structure declaration would be

struct key{
	char * word;
	int count;
}keytab[NKEYS];

Also written as

struct key{
	char *word;
	int count;
};

struct key keytab[NKEYS];

In the application structure contains a lot of constants hence better to use the first approach and initialize the array on definition.

struct key{
	char* word;
	int count;
}keytab[] = {
		"auto",0,
		"break",0,
		"while",0
}

can include braces for each element as well.

Can iterate through keys with number of keys known but if its subject to change another possibility is to terminate the list with a null pointer.

But since size of array determined at compile time number of elements is simply.

sizeof(keytab)/sizeof(struct key)

then

#define NKEYS (sizeof keytab / sizeof(struct key))

// Or type independent
#define NKEYS (sizeof keytab/ sizeof(keytab[0])

6.4 Pointers to Structures