为什么声明“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 returnerror: 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 

用你的语法着色编辑器试试最后一个;-)