为什么陈述“ 2i;” 不会导致编译器错误?


82

相反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

那是什么编译器?
Iharob Al Asimi '16

我不处理_Complex数字。阅读标准和提供的链接后,我认为@iharob的答案是正确的。
对于这个网站来说太老实了

@Olaf西方变换的fastet傅立叶FFTW使用的_Complex类型。我在为自己的论文编写数据处理软件(实际上是物理,而不是计算机科学等)时发现了这一点-(我必须应用低通滤波器,所以卷积就是快速傅立叶变换,所以fftw)。
Iharob Al Asimi

@iharob:嗯,那比ffte快吗?如果不是,我住在西部但在您东部的情况下,我可以使用更快的速度吗?;-)认真:感谢您的信息。看起来,C标准甚至不支持与C11类似的简单符号。
对于这个网站来说太老实了

一个很好的例子:“ ..不是'Eureka'而是'That's funny ...'”!
Jongware '16

Answers:


107

这是gcc扩展2i是虚数常量在此处输入图片说明。因此,您可以这样写一个复数:

#include <complex.h>

_Complex x = 4 + 5i;

12
哇,这真是令人惊讶!你能告诉我为什么即使我不包含complex.h头文件时它仍然起作用吗?
daltonfury42 '02

4
@ daltonfury42标头用于该_Complex类型,2i是一个常量(如gcc理解)。将std=c99std=c11标志加组合在一起-Wall,您将看到警告。另外,实际上它不会返回,0但是由于返回类型应该是_Complex和值0 + 2i,因此您无法使用进行检查printf()。所以也许那只是真正的部分0
Iharob Al Asimi '16

12
@ daltonfury42:您也不必#include <float.h>(或math.h)获得对浮点常量的支持。
对于这个网站来说太老实了

2
@ daltonfury42是的。头文件不改变语言的语法,他们只是声明之类的变量,函数,类型等
Barmar

2
@ daltonfury42虽然它可能是有可能识别这种语法来通过控制#pragma,这complex.h可以发行。但是他们没有这样做。
巴马尔

13

2igcc复数整数文字的扩展,它是的平方根的两倍的纯虚数-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

该语法可以以任何顺序与其他后缀组合。编译下面的代码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

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


嗯,这就是我在运行Arch Linux的PC上使用GCC 5.3.0时得到的。如果您有兴趣,是我的gcc配置。
daltonfury42 '02
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.