为什么声明“2i;”不会导致编译器错误?
而不是2*i
,我不小心写了2i
:
int foo(int i) { 2i; return 2i; }
我希望编译器能够发现错误。 但事实并非如此。 那么2i
是C中的一个有效陈述? 如果是的话,它是做什么的? 困惑!
我编译使用GCC版本5.3.0,这里是汇编输出:
.file "strange.c" .text .globl foo .type foo, @function foo: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl %edi, -4(%rbp) nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size foo, .-foo .ident "GCC: (GNU) 5.3.0" .section .note.GNU-stack,"",@progbits
这是一个gcc扩展 ,而2i
是虚数常量 。 所以你可以这样写一个复数:
#include <complex.h> _Complex x = 4 + 5i;
2i
是一个复数整数字面积的gcc
扩展,是-1
平方根两倍的纯虚数。 这个扩展也是由clang
支持的。
使用gcc 5.4.0
编译会生成张贴的程序集输出,这有些令人惊讶:
- 在http://gcc.godbolt.org/上编译我从;
gcc
5.3.0得到一个编译错误:http://gcc.godbolt.org/#
:error: cannot convert '__complex__ int' to 'int' in return
:error: cannot convert '__complex__ int' to 'int' in return
。 - 函数
foo
的过帐汇编代码不正确:它不返回0
。 将复数整型常量2i
转换为int
应返回其实部0
。
相反,在3.7节,它编译没有警告,并产生最佳的代码,但当然不是你所期望的:
foo(int): # @foo(int) xorl %eax, %eax retq
此语法可以按任何顺序与其他后缀组合。 用clang -Weverything
编译下面的代码clang -Weverything
给了我适当的警告warning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant]
:
#include <stdio.h> int main() { /* complex integer literals */ printf("sizeof(2i) = %zd\n", sizeof(2i)); printf("sizeof(2ui) = %zd\n", sizeof(2ui)); printf("sizeof(2li) = %zd\n", sizeof(2li)); printf("sizeof(2lli) = %zd\n", sizeof(2lli)); /* complex floating point literals */ printf("sizeof(2.i) = %zd\n", sizeof(2.i)); printf("sizeof(2.fi) = %zd\n", sizeof(2.fi)); printf("sizeof(2e0fi) = %zd\n", sizeof(2e0fi)); printf("sizeof(2e0i) = %zd\n", sizeof(2e0i)); /* alternate order */ printf("sizeof(2il) = %zd\n", sizeof(2il)); printf("sizeof(2ill) = %zd\n", sizeof(2ill)); printf("sizeof(2.if) = %zd\n", sizeof(2.if)); return 0; }
它在我的环境中产生这个输出:
sizeof(2i) = 8 sizeof(2ui) = 8 sizeof(2li) = 16 sizeof(2lli) = 16 sizeof(2.i) = 16 sizeof(2.fi) = 8 sizeof(2e0fi) = 8 sizeof(2e0i) = 16 sizeof(2il) = 16 sizeof(2ill) = 16 sizeof(2.if) = 8
用你的语法着色编辑器试试最后一个;-)