《C专家编程》是一本94年出版的讲语言的书,如今二十一世纪都已经过去十年多了,书上很多东西是不是依旧有用将是本文将要解答的问题。
尽量不要使用无符号数
当无符号数与有符号数再一起使用时,有符号数会被强转为无符号数。
|
|
解释:C在计算含有不同类型表达式时,会将类型向上提升,上面代码中的int被提升为了unsigned int,使-1的补码被解析为很大的整数。
相邻的自字符串会被合并
|
|
优先级的问题
. 比 * 高:
|
|
[] 比 * 高:
|
|
函数() 比 * 高:
|
|
==和!= 比 位操作符 高:
|
|
==和!= 比 赋值 高:
|
|
算数运算 比 位移运算 高:
|
|
优先级最低:
|
|
拆分声明、定义、typedef
- 找标识符
- 找被括号括起来的部分
- 找后缀操作符,如果是(),则表示是函数;如果是[],则表示是数组
- 找前缀操作符,如果是*,则表示指向某某的指针
- 找const和volatile,如果const,volatile紧跟类型,那么它作用于类型,其他情况下,作用于左边紧邻的项。
|
|
左值和右值
左值通常表示存储结果的地址,在编译时可知右值表示地址的内容,值仅当运行时才被确定。
指针与数组名不等同的情况(定义为数组,却声明为指针,反之同)
假设定义:int array[10], *ptr; (1)使用数组名下表访问(array[1]),会直接将数组名的地址加上偏移值作为变量的地址。 (2)使用指针下表访问(ptr[1]),会先取指针指向的内容,然后将这个内容加上偏移值作为变量的地址。 原因:当定义为数组时,却声明为指针时,相当于用指针下表访问的方法来解析一个数组名下标,即先取数组第0号元素的内容,然后将这个东西加上偏移值作为变量的地址,从而访问了不该访问的东西。反之同。
数组与指针等同的情况
(1)编译器将表达式中的数组名当作指向该数组第0号元素的指针,下标当作指针的偏移量,array[i]被作为*(array+i); (2)编译器将函数参数声明中的数组名当作指向该数组第0号元素的指针,即在函数内部得到的是指针,而不是数组名。 根据(1),可知道下面这条为谣言: 用指针迭代数组比用下标迭代数组更快 根据(2),可以解释为什么在传递数组后,不能使用下方法计算数组长度:
|
|
值得注意的是(2)中将数组改写为指针不是递归定义: 实参char hello[10][10]被改写为char (*hello)[10],这里将数组的数组改写为数组的指针 实参char *hello[10]被改写为char **hello,这里将指针数组改写为指针的指针 实参char (*hello)[10]不被改变,因为这时hello是指针非数组
interposition
interposition指的是用户定义的函数取代库中声明完全相同的函数,注意这不是指重载,而是指:
|
|
出现interposition时,需要注意:
|
|
注意:出现interposition时,vs2012会警告:inconsistent dll linkage
堆栈段作用
(1)存储局部变量 (2)函数调用时,存储有关的维护信息 (3)用作暂时存储区: 计算一个很长的表达式时,会把部分结果先压到堆栈中。