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 to , or to .
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:
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.
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,
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.
The expression ++i and i++ are identical if they appear as a statement by themselves; however, the return value is:
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.
If array is assigned an array, it stores the address of the first entry. Consequently,
*(array + n);
is equivalent to
array[n];
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.
The express 1 << n is identical to calculating for integer data types.
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 }
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.