web-dev-qa-db-ja.com

なぜ「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
82
daltonfury42

これは gcc拡張 、および2iは虚数定数です enter image description here 。したがって、次のように複素数を書くことができます。

#include <complex.h>

_Complex x = 4 + 5i;
106
Iharob Al Asimi

2iは、-1の平方根の2倍の純粋な虚数である複素整数リテラルのgcc拡張です。この拡張機能は、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を返しません。複素整数定数2iintに変換すると、実部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

シンタックスカラーリングエディターで最後の1つを試してください;-)

13
chqrlie