【问题标题】:Why does the statement "2i;" NOT cause a compiler error?为什么声明“2i;”不会导致编译器错误?
【发布时间】:2016-05-13 01:03:10
【问题描述】:

我不小心写了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

【问题讨论】:

  • 那是什么编译器?
  • 我不使用_Complex 号码。在阅读了一些标准和提供的链接之后,我认为@iharob 的回答是正确的。
  • @Olaf 西方的fastet傅里叶变换fftw使用_Complex类型。我在为我的论文编写数据处理软件时发现了这一点(实际上是物理学,而不是计算机科学或类似的科学)-(我必须应用低通滤波器,所以卷积所以快速傅里叶变换,所以fftw)。
  • @iharob:嗯,这比 ffte 快吗?如果不是,如果我住在西部,但在你的东部,我可以使用更快的吗? ;-) 说真的:感谢您提供的信息。看起来,C 标准甚至不支持与 C11 类似的简单表示法。
  • 一个很好的例子“......不是'Eureka'而是'这很有趣......'”!

标签: c syntax


【解决方案1】:

这是一个gcc extension,而2i 是虚常数。所以你可以像这样写一个复数:

#include <complex.h>

_Complex x = 4 + 5i;

【讨论】:

  • 哇,真是个惊喜!你能告诉我为什么即使我没有包含 complex.h 头文件它也能工作吗?
  • @daltonfury42 标头用于_Complex 类型,2i 是一个常量(gcc 理解它)。添加std=c99std=c11 标志并结合-Wall,您将看到警告。此外,它确实不返回0,但由于返回类型应该是_Complex 和值0 + 2i,你不能用printf() 检查它。所以也许这只是真正的部分0
  • @daltonfury42:您也不必通过#include &lt;float.h&gt;(或math.h)获得对浮点常量的支持。
  • @daltonfury42 没错。头文件不会改变语言语法,它们只是声明变量、函数、类型等。
  • @daltonfury42 尽管有可能通过#pragma 控制对这种语法的识别,complex.h 可能会发出此问题。但他们没有这样做。
【解决方案2】:

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
  • 发布的函数foo 的汇编代码不正确:它不返回0。将复整数常量 2i 转换为 int 应该返回其实部 0

相反,使用clang 3.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 时得到的结果。 Here 是我的 gcc 配置,如果你有兴趣的话。
猜你喜欢
  • 1970-01-01
  • 2011-06-09
  • 2019-01-30
  • 2020-04-26
  • 2019-11-18
  • 2016-11-08
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多