分类目录归档:『 K&R』

K&R: 60 tips of C programming language [3]

  • 41. Any operation that can be achieved by array subscripting can also be done with pointers. The pointer version will in general be faster but, at least to the uninitiated, somewhat harder to understand.
  • 42. All pointer arithmetic, is that pa+1 points to the next object, and pa+i points to the i-th object beyond pa.
  • 43. One difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.
  • 44. p[-1], p[-2] and so on are syntactically legal, and refer to the elements that immediately precede p[0].
  • 45. The valid pointer operations are assignment of pointers of the same type, adding or subtracting a pointer and an integer, subtracting or comparing two pointers to members of the same array, and assigning or comparing to zero. All other pointer arithmetic is illegal. To assign a pointer of one type to a ponter of another type without a cast is illegal except for void*.
  • 46. C does not provide any operators for processing an entire string of characters as a unit. It uses pointer.
  • 47. If a two-dimensional array is to be passed to a function, the parameter declaration in the function must include the number of columns.
  • 48. The format argument of printf can be an expression such like printf((argc > 1) ? "%s " : "%s", *++argv);.
  • 49. *++argv is a pointer to an argument string, so (*++argv)[0] is its first character.
  • 50. Any pionter can be cast to void* and back again without loss of information.
  • 51. A struct declaration defines a type. The right brace that terminates the list of members may be followed by a list of variables. struct{...} x, y, z; is syntactically analogous to int x, y, z;.
  • 52. A structure declaration that is not followed by a list of variables reserves no storage.
  • 53. The only legal oprations on a structure are copying it or assigning to it as a unit, taking its address with &, and accessing its members.
  • 54. *p->str fetches whatever str points to; *p->str++ increments str after accessing whatever it points to (just like *s++); (*p->str)++ increments whatever str points to; and *p++->str increments p after accessing whatever str points to.
  • 55. It is illegal for a structure to contain an instance of itself but declares a pointer to it is legal.
  • 56. A typedef declaration does not create a new type in any sense; it merely adds a new name for some existing type.
  • 57. For example, typedef int (*PFI)(char *, char *); creates the type PFI, for "pointer to function (of two char * arguments) returning int," which can be used in contexts like PFI strcmp, numcmp;.
  • 58. The same operations are permitted on unioins as on unions as on structures: assignment to or copying as a unit, taking the address ,and accessing a member.
  • 59. A union may only be initialized with a value of the type of its first member; thus the union u described above can be initialized with an integer value.
  • 60. The & operator cannot be applied to bit-field because they are not arrays and they do not have addresses.
  • --EOF--

    K&R: 60 tips of C programming language [2]

  • 20. Variables can be declared inside any block; not only have to declare at the entry of the function.
  • 21. All case expressions must be different in switch statement. Cases and the default clause can occur in any order.
  • 22. The commas that separate function arguments, variables in declarations, etc., are not comma operators, and do not guarantee left to right evaluation.
  • 23. A label has the same form as a variable name, and is followd by a colon. The scope of a label is the entire function.
  • 24. Functions themselves are always external, because C does not allow functions to be defined inside other functions.
  • 25. If a large number of variables must be shared among functions, external variables are more convenient and efficient that long argument lists.
  • 26. The scope of an external variable or a function lasts from the point at which it is declared to the end of the file being complied.
  • 27. There must be only one definition of an external variable among all the files that make up the source program; other files may contain extern declarations to access it. Array sizes must be specified with the definition, but are optional with an extern declaration.
  • 28. If a function is decleared static, howerer, its name is invisible outside of the file in which it is decleared.
  • 29. The register declaration can only be applied to automatic variables and to the formal parameters of a function. It is not possible to take the address of register variable, regardless of whether the variable is actually placed in a register.
  • 30. External and static variables are guaranteed to initialized to zero; automatic and register vaiables have undefined initial values. For external and static vairables, the initializer must be a constant expression.
  • 31. If there are fewer initializers for an array than the number specified, the missing elements will be zero for external, static, and atutomatic variables.
  • 32. One simplest version of quicksort:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
     /* sort v[left] ... v[right] into increasing order */
    void qsort(int v[], int left, int right)
    {
    	int i, last;
    	void swap(int v[], int i, int j);
     
    	if(left >= right)
    		return;
    	swap(v, left, (left + right)/2);
    	last = left;
    	for(i = left + 1; i <= right; i++)
    	{
    		if (v[i] < v[left])
    			swap(v, ++last, i);
    	}
    	swap(v, left, last);
    	qsort(v, left, last-1);
    	qsort(v, last+1, right);
    }
     
    void swap(int v[], int i, int j)
    {
    	int temp;
     
    	temp = v[i];
    	v[i] = v[j];
    	v[j] = temp;
    }
  • 33. When an included file is changed, all files that depend on it must be recompiled.
  • 34. The name in a #define has the same form as a variable name; the scope of a name defined with #define is from its point of definition to the end of the source file being compiled.
  • 35. Names may be undefined with #undef, usually to ensure that a routine is really a function, not a macro:
  • 1
    2
    
     #undef getchar
    int getchar(void) {}
  • 36. In macro, if a parameter name is preceded by a # in the replacement text, the combination will be expanded into a quoted string with the parameter replaced by teh actual argument.
    1
    2
    3
    4
    
     #define dprint(expr) printf(#expr " = %g\n", expr)
     
    dprint(x/y);//it has the same meaning of following expression.
    printf("x/y" " = %g\n", x/y);
  • 37.The preprocessor operator ## provides a way to concatenate actual arguments during macro expansion.
    #define paste(font, back) front ## back

    so paste(name, 1) creates the token name1.

  • 38. In ANSI C, the type void* replaces char* as the proper type for a generic pointer.
  • 39. The & operator only applies to objects in memory: variables and array elements. It cannot be applied to expressions, constants, or register variables.
  • 40. Unary operators like * and ++ associate right to left. So *ip++ means *(ip++), quite far different from (*ip)++.
  • --EOF--

    K&R: 60 tips of C programming language [1]

    曾经一段时间经常会去Google Groups的comp.lang.c小组里逛逛。在那里,『The C Programming Language』(Kernighan&Richie著,以下简称K&R)是被当成神作供起来的,简直就是C语言领域的“圣经”。于是当时慕名下了电子书看了有一半左右,因为e文不好看着非常累,虽然看后感觉挺有收获,但还是放弃了没有看完。后来不知道哪一次脑热买了K&R实体书,过去几年,它一直沉睡在那里。如今,陆陆续续接触到了各种五花八门的编程语言,C语言除了考试和面试反而不怎么用到了,但是没读完这本书却始终觉得人生不完整。于是,强迫自己将它翻完一遍,感觉真的是非常基础,讲得也透彻,我都不知道用什么词汇去形容它的浅显和通俗了。如果入门时授课老师用这本书当教材应该是个不错的选择。

    读完一遍K&R,顿时觉得程序人生又完整了一些,现在做个总结。

  • 1. Comments may appear anywhere a blank or tab or newline can.
  • 2. printf is not part of C language; there is no input or output defined in C itself. printf is just a useful function from the standard libray of functions that are normally acessible to C programs. printf recognizes %% for % itself. printf uses %f for both float and double.
  • 3. getchar() returns a distinctive value when there is no more input. We can't define a char value to hold the return value of getchar() because char is not big enough to hold EOF in addition to any possible char. Use int instead.
  • 4. A character written between single quotes represents an integer value equal to the numerical value of the character in the machine's character set.
  • 5. With properly designed functions, it is possible to ignore how a job is done; knowing what is done is sufficient.
  • 6. In C, all function arguments are passed "by value." This means that the called function is given the values of its garguments in temporary variables rather than the originals. int is the default return type of function, it could be omitted.
  • 7. An external variable must be defined, exactly once, outside of any funtion.
  • 8. "Definition" refers to the place where the variable is created or assigned storage; "Declaration" refers to places where the nature of the variable is stated but no storage is allocated.
  • 9. Begin variable names with underscore is legal but not recommend, since library routines often use such names.
  • 10. A leading 0 (zero) on an integer constant means octal; a leading 0x or 0X means hexadecimal.
  • 11. String constants can be concatenated at complie time: "hello," "world" is equivalent to "hello, world". char st[] = "hello, " "world!"; is legal.
  • 12. If not all values are specified in enumerations, unspecified values continue the progression from the last specified value. Names in different enumerations must be distinct. Values need not be distinct in the same enumeration. Enumeration variables offer the chance of checking and so are often better than #define.
  • 13. External and static variables are initialized to zero by default.
  • 14. The % operator cannot be applied to float or double.
  • 15. The increment and decrement operators can only be applied to variables; an expression like (i+j)++ is illegal.
  • 16.Bitwise operators like &,|,^,<<,>>,~ only be applied to integral operands, that is char, short, int and long, whether signed or unsigned.
  • 17. x *= y + 1 means x = x * (y + 1) rather than x = x * y + 1.
  • 18. An bitcount function:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
     /* bitcount: count 1 bits in x */
    int bitcount (unsigned x)
    {
    	int b;
     
    	for (b = 0; x != 0; x >>= 1)
    	{
    		if (x & 01)
    			b++;
    	}
    	return b;
    }

    Declaring the argument x to be unsigned ensures that when it is right-shifted, vacated bits will be filled with zeros, not sign bits, regardless of the machine the program is run on.

  • 19. printf("%d %d\n", ++n, power(2, n)); can produce different results with different compilers, depending on whether n is incremented before power is called.
  • --EOF--