c语言特殊运算符号大全,运算符,一种特殊的标识符----小话c语言(8)

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

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;

}

运行结果:

1337048618_4460.png

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;

} 编译运行:

1337049290_9298.png

这里先介绍下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;

}

运行结果:

1337050221_1118.png

按照上面的代码,~c应该得到的是0x03, 那么结果应该是0x03, 怎么会是上面图片的结果呢?

A: 这是因为位运算是被提升到整形运算的。上面的变量c是无符号字符型,在进行~位运算时,是首先提升为整形,即为0x000000fc, 然后

取反得到0xffffff03, 所以i得到的数值是这个。同理,如果c是char类型,提升为整形时为0xfffffffc,再取反得到的就是

0x03.其实变量被提升有很多地方,比如short计算时也会提升为int再继续计算。