《C语言深度解剖》小记
今日阅读一本不错的书,叫《C语言深度解剖》
做一些读书笔记:
关于register修饰符注意点:虽然寄存器速度非常快,但是用register修饰符也有一些限制的:register变量必须是能被CPU寄存器所接受的类型。意味着register变量必须是一个单个的值,并且其长度应小于或者等于整型的长度。而且register变量可能不存放在内存中,所以不能用取地址运算符“&”来获取register变量的地址。
关于sizeof:sizeof在计算变量所占空间大小时,括号可以省略,而计算类型(如int)大小时不能省略。一般情况下,不要偷懒,乖乖加上括号,继续假装它是一个函数。严重提醒,sizeof不是函数。
对于case语句:case后面的只能是整型或字符型的常量或常量表达式。
Float变量与“零值”进行比较:
Float fTestVal = 0.0;
A), if(fTestVal == 0.0); if(fTestVal != 0.0);
B), if((fTestVal >= -EPSINON) && (fTestVal <= EPSINON));//EPSINON为定义好的精度
EPSINON为定义好的精度,如果一个数落在[0.0-EPSINON,0.0+EPSINON]这个闭区间内,我们认为在某个精度内它的值与零值相等;否则不相等。扩展一下,把0.0替换为你想比较的任何一个浮点数,那我们就可以比较任意两个浮点数的大小了,当然是在某个精度内。
有关void : Void 的字面意思是“空类型”,void *则可以指向任何类型的数据。Void 真正发挥的作用在于:1.对函数返回的限定;2.对函数参数的限定。
关于const :const修饰的只读变量不能用来作为定义数组的维数,也不能放在case关键字后面。
a与&a的区别:看程序:
main()
{
int a[5] = {1,2,3,4,5};
int *ptr = (int *)(&a + 1);
printf(“%d,%d”, *(a + 1),*(ptr - 1));
}
对指针进行加1操作,得到的是下一个元素的地址,而不是原有的地址值直接加1.所以,一个类型为T的指针的移动,以sizeof(T)为移动单位。因此,对于上述程序来说,a是一个一维数组,数组中有5个元素;ptr是一个int型的指针。
&a + 1:取数组a的首地址,该地址的值加上了sizeof(a)的值,即&a + 5*sizeof(int),也就是下一个数组的首地址,显然当前指针已经越过了数组的界限。
(int *)(&a + 1):则是把上一步计算出来的地址,强制转换为int* 类型,复制给ptr。
*(a + 1): a, &a的值是一样的,但是意思不一样,a是数组首元素的首地址,也就是a[0]的首地址,&a是数组的首地址,a + 1是数组下一元素的首地址,即a[1]的首地址,&a + 1是下一个数组的首地址。所以输出2
*(ptr-1):因为ptr 是指5,并且ptr是int * 类型,所以*(ptr - 1)是指向a[4]输出5.