1.数值是以引用(reference)形式进行传递,也就是传址调用;标量和常量按值(value)传递。所有传递给函数的参数都是按值传递的,但是,数组名作为参数时就会产生按引用传递的效果。
/*个人观点:数组其实是指针应用的一个特例,所以编译器没有必要去检查数组下标是否越界,当然,这也提高了编译的效率。*/
2.不良的风格和不良的文档是软件生产和维护代价高昂的两个重要原因。在函数定义中,返回类型出现在独立一行中,而函数名则出现在下一行起始处,这样在寻找函数定义时,你可以在一行的开头处找到函数的名字。
/*作者的经验,可以参考,但未必符合每个人的习惯*/
3.数组使用方面的一个良好经验法则:如果下标值是从那些已知是正确的值计算得来,那么就无需检查它的值,如果一个用作下标的值是根据某种方法从用户输入的数据产生而来的,那么在使用它之前必须进行检测,确保它们位于有效范围之内。
4.容易“被愚弄”的地方:
1)声明指针:
例如:int* b, c, d;
人们很自然地以为这条语句把所有三个变量都声明为指向整型的指针,但事实上星号是表达式*b的一部分,只对这个标识符有用。b是一个指针,其余两个变量c、d只是普通的整型。要声明三个指针,正确的语句是:
int *b, *c, *d;
2)声明指针并赋值:
例如:char *message = “Hello world”;
这条语句是指message声明为一个指向字符的指针,并用字符串常量中的第一个字符的地址对该指针进行初始化。这样的声明很容易引起误解,看上去好像初始值是赋给了表达式*message,事实上它是赋给了message本身。上面的声明相当于:
char *message;
message = “Hello world”;
5.创建新的类型名,宜使用typedef而不用#define,因为后者无法正确处理指针类型,如:
#define d_ptr_to_char char *
d_ptr_to_char a, b;
正确地声明了a,但b却被声明为一个字符。如果使用typedef就会避免这个问题。
6.常量与指针在一块使用的情况:
int const *pc;//是一个指向整型常量的指针,可修改指针的值,但不能修改它所指向的值。
int *const cp;//是一个指向整型的常量指什,此时,指针是常量,它的值无法修改,但可以修改它所指向的整型的值。
int const *const ccp; //无论指针本身还是它所指向的值,都是常量均不允许修改。
7.对于auto变量,除了声明为const的变量外,在声明变量的同时进行初始化和声明后赋值只有风格之差,并无效率之别。
8.当static用于函数定义时,或用于代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响,用这种方式声明的函数或变量只能在声明它们的源文件中访问。
当用于代码内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行前创建,并在程序的整个执行期间一直存在,而不是每次在代码块开始执行时创建,在代码执行完毕后销毁。
9. for语句和while语句执行过程的区别在于出现continue语句时。在for语句中,continue语句跳过循环体的剩余部分,直接回到调整部分;在while语句中,调整部分是循环体的一部分,所以continue语句将会把它也跳过。
for循环有一个风格上的优势,它把所有用于控制循环的表达式收集在一起,放在同一处,便于寻找。
10.跳出多层嵌套循环的方法:
1)使用goto语句,因为break语句只影响包围它的最内层循环体;
2)当希望退出所有循环时设置一个状态标志,但这个标志在每个循环中都必须进行测试;
3)把所有循环放在一个单独的函数中,当要从最内层循环跳出时,使用return语句离开这个函数。