前言:
此时同学们对“c语言参数宏”大致比较关怀,看官们都想要知道一些“c语言参数宏”的相关内容。那么小编同时在网摘上网罗了一些关于“c语言参数宏””的相关知识,希望大家能喜欢,你们一起来学习一下吧!首先,我声明一下,这篇文章适合想理解c的人群来看的,当然不是说我特别厉害什么的,因为只是一个小知识点而已,主要是我是从用户的角度来看的,我这篇文章在我写完的时候,发现并没是没什么图片的,没有什么兴趣点,只有理论的。若是我来看的话,我也不会去看的。所以,怎么说尼,慢慢看是一定会看懂得。若是看不懂算我输,若是觉得很繁琐还是建议直接退出为好。
INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
最小占用长度为int的整数倍的意思是字节小于或者等于4字节的,那么_INTSIZEOF(n)的值就是4,而大于4的就是4的倍数的字节数。这个宏的整体结构就是输入的字节数是4个字节的多少个,然后在乘以4字节就是宏的值,比如n是double,那么sizeof(double)就是8字节,也就是sizeof(int)的2倍,然后再乘以4字节(也就是2*4 = 8)字节那么这个红就是8字节,若是char,那么这个宏的值就是4字节。
理解这个宏需要点数学知识,先举个例子,假设一个盒子能放2个球,目前有6个球,那么就需要3个盒子,若是有5个球,那么还是需要3个盒子。扩展一下,若是有n个球,每个盒子能容乃下m个球,那么需要多少个盒子???这里直接给出结论就是(n + m - 1)/m个,当然"/"就如c语言中的“/”一个意思也就是商取整数的形式。这里简单的列出证明的过程:
1):若是n为m的整数倍,即n=mx,那么带入上式,(mx + m - 1)/m = x + (m -1)/m,由于"/"表示取整,那么(m - 1)/m就为0,所以(mx + m - 1)/m = x。
2):若是n不为m的整数倍,即n=mx+r(1 <= r < m),带入上式(n + m - 1)/m中就是
(mx + r + m - 1)/m = x + (m+r-1)/m;由于1 <= r < m,所以m <= (m+r-1) <2m-1<2m ,那么也就是1 <= (m+r-1)/m <2,由于"/"表示取整,所以(m + r -1)/m = 1,所以(n + m - 1)/m = x + 1。注意这里的x,根据n=mx+r,x的意思是m的整数倍,当n不为m的整数倍时就需要x+1个,正好当n不为m的整数倍时,就需要x + 1个盒子,也就是要(n + m - 1)/m个盒子。
结合1),2)得出的结论就是(n + m - 1)/m,我们再来看看上面的宏#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ),这里的(sizeof(n) + sizeof(int) - 1)是不是很像(n + m - 1),sizeof(n)可以理解为有n个球,sizeof(int)可以理解为一个盒子能容纳m个球。
接下来我们分析一下& ~(sizeof(int) - 1)是什么意思,再知道这以前我们得先假设m为2的幂的某一个数,也就是m = 2^x次方,然后结合计算机的基础知识来解释。上面说了这个宏的结构就是输入的字节数是4个字节的多少倍,然后在乘以4字节就是宏的值。为了方便,我们设n = sizeof(n),m = sizeof(int),也就是(n + m - 1)/m中的n和m,那么我们可以得到(n + m - 1)/m的意思就是sizeof(n)是需要(n + m - 1)/m = x个sizeof(int),那么x * m就是这个宏的值,也就是((n + m - 1)/m ) * m就是宏的值,注意数学与计算机科学的差别,数学上((n + m - 1)/m ) * m = (n + m - 1),但是在计算机科学上先除,在乘不会得到原值的,原因就是(n + m - 1)/m = (n+m-1) >> x(上面假设了m = 2^x),也就是(n+m-1) 向右移动x位(因为某一个二进制数除以2(2 = 2^1)表示向右移动1(次幂)位,所以这里移动了x位),然后在向做移动x位,这个值很明显就不是原值了,比如1111,右移动2位就是0011了,在左移动2位就为1100了这就不是1111了。上面说了((n + m - 1)/m ) * m就是宏的值,((n + m - 1)/m ) * m也就是((n + m - 1)>>x)<<x,那么((n + m - 1)>>x)<<x与& ~(sizeof(int) - 1)有什么联系???(n + m - 1)右移动x位,在左移动x位,也就是把(n + m - 1)二进制形势下的最右边的x位全清为0了,比如上面的例子1111右移动2位,在左移动2位得到了1100,所以我们可以发现((n + m - 1)>>x)<<x就是把最右边的x位全清为0了,那么(n + m - 1)与上某一个值把最右边的x位全清0,那么整个分析就算结束了,答案就不说,也就是上面的~(sizeof(int) - 1)。我肯定是推不出这个解果的,推不出不要紧,我们先理解它。首先sizeof(int)是2的2次幂,二进制形式是0100,我们从这个0100出发,上面说了,(n + m - 1)要先右移动x位,在左移动x位,而m = 2^x =sizeof(int),那么x = 2的。我们结合这个x(在这里该值为2)与0100来理解这个式子~(sizeof(int) - 1),我们得目的是使得(n + m - 1)的最右边x(x = 2)位清0,注意0100只有一个1,先把0100减去一个1,也就是3(二进制的形式为0011),写到这想必就能理解了,在取一个反不就正好只把最右边的两位清0了,其他位不变,不正好就是我们要的式子吗!!!别急,我们在想想为什么要先减1,我们来看这个二进制0100,从二进制的加减法运算的角度来分析,0x0100 -1 是等于0x0011的,就是因为0x0100,只有一个1的存在,其他为0了,0x0100在减1的时候,导致1后面的其他位全为1,而全为1的个数正好在最右边,而且正好为幂(此时的幂为2)的个数,你说巧不巧!!!比如要为double的整数倍,这里sizeof(double) = 8 ,8的二进制为1000,减1为0111,取反1000,正好最右边三个0,所以解决这个问题的关键就是m为2的幂次方也就是m = 2^x次方(x为整数),不然结论是不成立的。
所以((n + m - 1)/m ) * m = ((n + m - 1)>>x)<<x = (n + m - 1) & ~(m - 1),((n + m - 1)/m ) * m的物理意义就是sizeof(n)需要多少个sizeof(int)才能满足,然后在乘以m表示总共需要的字节数(个数*字节数 = 总字节数),然后根据上面的等式就得到了(n + m - 1) & ~(m - 1),也就是这个宏的由来了!!!
标签: #c语言参数宏 #c语言不定参数怎么表示 #c语言不定参数怎么表示出来 #c语言 不定参数