Skip to the content of the web site.

C Tricks

Some of you will be working at co-op placements where C will be the language of choice. In this course, I try to use unambiguous programming examples where common tricks are not used. In the old days of C, the compilers did minimal optimization, and therefore many of the features of C are often used in order to force certain optimizations at the assembly language level. These days, however, compilers often have optimizers that are significantly better than programmers and consequently, it is in the programmer's best interest to focus on the algorithms and data structures used which can change the run time from tex:$$O(n^2)$$ to tex:$$O(n ln(n))$$, or tex:$$O(n)$$ to tex:$$\Theta(1)$$.

Never-the-less, many programmers insist on using many of the tricks which may, to the untutored eye, appear somewhat obfuscated—indeed, there is the International Obfuscated C Code Contest which allows indiviudals, for example, to write code the prints the secular holiday song Twelve Days of Christmas, we have

#include<stdio.h>
main(t,_,a)char *a;{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main
(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,"@n'+,#'/*{}w+/w#\
cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#;#q#n+,/+\
k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'\
r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#\
w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l\
##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc\
,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"):t< -
50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1):0<t
?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,"!ek;dc i@bK'(q)-[w]*%\
n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}

so while the source code is only 818 characters, the output is 2358 characters in length. There is another interesting peice of code that prints itself. It is always fun to try to find and correct the typo in the above code.

Here are some common short cuts:

Example

0 is false and any other number is true. Thus,

	for ( i = 10; i != 0; --i ) {
		// loop body
	}

is identical to

	for ( i = 10; i; --i ) {
		// loop body
	}

This is also true for floating-point numbres.

Example

	while ( (var = expr_1) != expr_2 ) {
		// loop body
	}

At the start of each loop, var is assigned the result of expr_1 and once it is assigned,

Example

A nicer one is, instead of doing

	if ( expr_1 ) {
		return expr_2;
	} else {
		return expr_3;
	}

you can simplify this to

	return ( expr_1 ) ? expr_2 : expr_3;

The ternary ?: operator evaluates the first expression and the the value returned by the operator is either expr_2 or expr_3 depending on whether expr_1 evaluated to 0 or 1.

Example

The expression ++i and i++ are identical if they appear as a statement by themselves; however, the return value is:

  • ++i increments i and returns the incremented value, while
  • i++ returns the original value of i.

Thus,

	i = 0;

	while ( array[i++] ) {
		// Loop body
	}

will examine locations 0, 1, 2, ... until it finds the first entry in the array equal to 0. The value of i will be the index of the entry following the entry with 0; while

	i = 0;

	while ( array[++i] ) {
		// Loop body
	}

will check the locations 1, 2, 3, ... unntil it finds the first entry of the array equal to 0 and i will be assigned that index.

Example

If array is assigned an array, it stores the address of the first entry. Consequently,

	*(array + n);

is equivalent to

	array[n];

Example

In declaring a pointer, each pointer must be given its own *:

	int*ptr, i;
	int *ptr, i;
	int* ptr, i;
	int * ptr, i;

all declare ptr to be a pointer to an integer while i is just an integer. This is the same for

	int i,*ptr;
	int i, *ptr;
	int i,* ptr;
	int i, * ptr;

Consequently, if you want two pointers, you must use

	int *p1, *p2;

Therefore, it is better to place the space before the * with no space between the * and the variable name.

Example

The express 1 << n is identical to calculating tex:$$2^n$$ for integer data types.

Example

In C, if a function has no parameters, it is usual to indicate this with void; while C++ does not require this.

int main( void ) {
	// C code
}

int main() {
	// C++ code
}

Example

All assignment operators are right associative: that is, they evaluate the second operator before making the assignment.

For example, in

	int a, b, c;

	a = b = c = 0;

Is equivalent to

	a = (b = (c = 0));

That is, c = 0 assigns c the value of 0 and the = operator returns 0. Now, that return value is assigned to b, and then returned when it is assigned to a.