C Notes
- 12 minsKernighan, 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;
}
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
int *pa;
pa = &a[0];
// pa points to zero element of a
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]
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
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])