为什么声明"2i;" 不会导致编译器错误?

dal*_*y42 82 c syntax

而不是2*i,我不小心写道2i:

int foo(int i)
{
    2i;
    return 2i;
}
Run Code Online (Sandbox Code Playgroud)

我希望编译器能够捕获错误.但事实并非如此.那么,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
Run Code Online (Sandbox Code Playgroud)

Iha*_*imi 107

这是一个gcc扩展,2i是虚数常量在此输入图像描述.所以你可以像这样编写一个复数:

#include <complex.h>

_Complex x = 4 + 5i;
Run Code Online (Sandbox Code Playgroud)

  • 哇,这真是一个惊喜!即使我没有包含complex.h头文件,你能告诉我为什么它有用吗? (12认同)
  • @ daltonfury42:您不必使用`#include <float.h>`(或`math.h`)来获得对_floating point constants_的支持. (12认同)
  • @ daltonfury42标题用于`_Complex`类型,`2i`是常量(*为gcc理解它*).添加`std = c99`或`std = c11`标志并结合`-Wall`,你会看到一个警告.确实,它不会返回"0",但由于返回类型应为`_Complex`且值为'0 + 2i`,因此无法使用`printf()`进行检查.所以也许这只是真正的**部分`0`! (4认同)
  • @ daltonfury42那是对的.头文件不会改变语言语法,只是声明变量,函数,类型等. (2认同)
  • @ daltonfury42虽然可以通过`#pragma`来控制这种语法的识别,但是`complex.h`可以发出.但他们并没有这样做. (2认同)

chq*_*lie 13

2i是一个gcc复数整数文字的扩展名,是两个平方根的纯虚数-1.此扩展也受到支持clang.

令人惊讶的是,您的编译gcc 5.4.0生成了已发布的程序集输出:

  • http://gcc.godbolt.org/#上编译我从gcc5.3.0 获得了编译错误http://gcc.godbolt.org/#:: error: cannot convert '__complex__ int' to 'int' in return.
  • 发布的函数汇编代码foo不正确:它不返回0.将复数整数常量转换2iint应返回其实部0.

相反,使用clang3.7时,它会在没有警告的情况下编译并生成最佳代码,但当然不是您所期望的:

foo(int):                       # @foo(int)
    xorl    %eax, %eax
    retq
Run Code Online (Sandbox Code Playgroud)

此语法可以按任何顺序与其他后缀组合.编译下面的代码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;
}
Run Code Online (Sandbox Code Playgroud)

它在我的环境中生成此输出:

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
Run Code Online (Sandbox Code Playgroud)

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