C

Mostly from K&R.

Variable

A variable (object) have two “values” associated. One is the actual value stored and the other the “value” of the memory location, i.e., the address. Some texts refer to these two values with the nomenclature rvalue (right value, pronounced “are value”) and lvalue (left value, pronounced “el value”) respectively. K&R II (page 197) says
“An object is a named region of storage; an lvalue is an expression referring to an object.”, which is kind of consistent.

int i, j;
i = 0; // i’s lvalue is used to set the numeric value
j = i; // i’s rvalue is used to set j

Extern and static variables are initialized to 0.

K&R says “automatic arrays may not be initialized” (p 83) but seems like all compilers allow it now.

Pointer and array

char* a = “stringA”; // needs 7+1 + 4 bytes
char b[] = “stringB”; // needs 7+1 bytes
are both legal, but a can’t be operated (*a++, a[1]) like b can. “stringA” is stored in data segment, whereas “stringB” on stack.

It’s better to think of array name as the address of its first element instead of just a pure pointer, since you can’t assign a pointer to an array name (it has const lvalue).

int *ap[3] is an array of pointer that has 3 elements. It’s clearer to have “int* ap[3]”.
int (*pa)[3] is a pointer to an array that has 3 elements.

typedef int a10array[10]; sizeof(a10array) = 40
a10array* pa; // same as int (*pa)[10]

a[i] = *(a+i) = *(i+a) = i[a]. VC++ allows it.

2D array: column size must be given in declaration and function argument. It can be passed as f1(int a[d1][d2]), f2(int a[][d2]), or f3(int* a). In the last case, element access is a[i*d2 + j]. If declaration is int a[3][5], f3 can be called as f3((int*)a), f3(a[0]), or f3(&a[0][0]).

For dynamic 2D array, if we want it to take contiguous memory block and save malloc() calls we can allocate the memory as a whole then set the second dimension pointers to the memory location:

int nRow = 3, nCol = 2;
int* pMemBlock = malloc(nRow * nCol * sizeof(int));
int** a2test = malloc(nRow * sizeof(int*));
for (int i = 0; i < nRow; i++)
{
a2test[i] = pMemBlock + i * nCol;
}

Pointer operation allowed: p++ p– *p &p p-> p+int p-int p-q (only meaningful if p, q points to elements in the SAME array)
NOT allowed: + * / << & etc.

Operator precedence

  1. parenthesis and scope: () [] -> .
  2. unary (right to left): ! ~ ++ — – (type) * & sizeof
  3. math: * / %; + -; << >>
  4. comparison: < <= > >=; == !=
  5. logical: &; ^; |; &&; ||
  6. tenary and assignment (right to left): ?:; = += -=

Some implication:
*p++ increments p, (*p)++ increments p’s value because ++ has precedence over *.
(*ptr2struct).element has to have parenthesis (of course you can use ptr2struct->element).

Misc

K&R say that “all float’s in an expression are converted to double; all floating point arithmetic in C is done in double precision”. In C++ float stays float.

calloc() sets memory to 0, malloc() doesn’t.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s