该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
A:
[cpp] view plaincopy
#include
int main()
{
int i = 1;
printf("%d\n", sizeof(i));
return 0;
}
它对应的汇编代码为(部分):
[cpp] view plaincopy
movl $4, %eax
xorb %cl, %cl
leaq L_.str(%rip), %rdx
movq %rdx, %rdi
movq %rax, %rsi
movb %cl, %al
callq _printf
笔者所在机器为x64架构,在x64上的参数传递,如果参数不超过6个,一般是先入寄存器,参数从左到右分别放入:rdi,rsi,rdx,rcx,r8,r9.
可以看到数字4直接放入了%eax, 最后用%eax的扩展寄存器%rax将数据放入%rsi; sizeof(i)的值在编译期就已经计算得到了4.
Q: sizeof后面可以跟表达式,下面的代码,为什么i++无效呢?
[cpp] view plaincopy
#include
int main()
{
int i = 1;
sizeof(i++);
printf("%d\n", i);
return 0;
}
运行结果:

A: 正因为sizeof是编译期求值的,所以如果它跟着表达式,那么表达式是不被计算的,只是根本表达式的类型得到它占用的空间。看下它的汇编:
[cpp] view plaincopy
movl $1, -12(%rbp)
movl -12(%rbp), %eax
xorb %cl, %cl
leaq L_.str(%rip), %rdx
movq %rdx, %rdi
movl %eax, %esi
movb %cl, %al
callq _printf
可以看到,调用printf函数之前直接将数据1当做参数输出,至于sizeof(i++)中的i++根本没有对应指令。
Q: 对于普通数组arr来说,sizeof(arr)可以确定arr的大小,那变长数组的sizeof如何计算呢?
A: 正因为是可变数组,所以sizeof计算它大小的过程将被推迟到运行时。
[cpp] view plaincopy
#include
#define PRINT_D(intValue) printf(#intValue" is %lu\n", (intValue));
size_t get_arr_len(int n)
{
char arr[n + 1];
return sizeof(arr);
}
int main()
{
PRINT_D(get_arr_len(1))
return 0;
} 编译运行:

这里先介绍下VLA(变长数组),它是c99引入的特性,表示一个数组的长度不一定在编译期就可以确定,可以推迟到运行时。
我们先看下上面代码的汇编(部分):
[cpp] view plaincopy
0x0000000100000dcc : add $0x1,%edi
0x0000000100000dcf : mov %edi,%ecx
0x0000000100000dd1 : mov %rsp,%rdx
0x0000000100000dd4 : mov %rdx,-0x20(%rbp)
0x0000000100000dd8 : mov %rcx,-0x10(%rbp)
0x0000000100000ddc : movl $0x1,-0x24(%rbp)
0x0000000100000de3 : mov -0x20(%rbp),%rcx
0x0000000100000de7 : mov %rcx,%rsp
0x0000000100000dea : mov -0x10(%rbp),%rcx
0x0000000100000dee : mov (%rax),%rax
0x0000000100000df1 : mov -0x8(%rbp),%rdx
0x0000000100000df5 : cmp %rdx,%rax
0x0000000100000df8 : mov %rcx,-0x30(%rbp)
0x0000000100000dfc : jne 0x100000e08
可以看到,第一行执行了get_arr_len中n+1的操作,最后将得到的数据传递到%ecx中,最终在倒数第二行的地方将此数据传递出去;可以看出是在运行时计算数组大小的。
Q: 如下代码关于位运算符的操作为何最终结果和预期不符?
[cpp] view plaincopy
#include
int main()
{
unsigned char c = 0xfc;
unsigned int i = ~c;
printf("%#x\n",i);
return 0;
}
运行结果:

按照上面的代码,~c应该得到的是0x03, 那么结果应该是0x03, 怎么会是上面图片的结果呢?
A: 这是因为位运算是被提升到整形运算的。上面的变量c是无符号字符型,在进行~位运算时,是首先提升为整形,即为0x000000fc, 然后
取反得到0xffffff03, 所以i得到的数值是这个。同理,如果c是char类型,提升为整形时为0xfffffffc,再取反得到的就是
0x03.其实变量被提升有很多地方,比如short计算时也会提升为int再继续计算。