「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 2016

私は_Complex数字を扱いません。標準と提供されたリンクを少し読んだ後、@ iharobの答えは正しいと思います。
このサイトには正直すぎる

fastetフーリエ西に変換@Olaf FFTW使用する_Complexタイプを。私は自分の論文のデータ処理ソフトウェアを書いているときにこれを見つけました(物理学、実際にはコンピューターサイエンスなどではありません)-(ローパスフィルターを適用する必要があったので、畳み込み、高速フーリエ変換、fftw)。
Iharob Al Asimi 2016

@iharob:うーん、それはffteよりも速いですか、そうでない場合、私が西に住んでいて、あなたの東に住んでいるなら、私はより速い使用を許可されますか?;-)真剣に:情報をありがとう。見た目では、C標準はC11と同様の単純な表記法さえサポートしていません。
このサイトには正直すぎる2016

「..「ユーレカ」ではなく「それはおもしろい...」」の非常に良い例です!
Jongware 2016

回答:


107

これはgcc拡張であり2i、虚数定数ここに画像の説明を入力してくださいです。したがって、次のような複素数を書くことができます。

#include <complex.h>

_Complex x = 4 + 5i;

12
うわー、それは驚きでした!complex.hヘッダーファイルをインクルードしなくても機能する理由を教えてください。
daltonfury42 2016

4
@ daltonfury42ヘッダーは_Complex型用で2iあり、定数です(gccが理解しているように)。std=c99またはstd=c11フラグを組み合わせて追加する-Wallと、警告が表示されます。また、実際には戻り値は返されません0が、戻り_Complex値の型はと値0 + 2iである必要があるため、で検査することはできませんprintf()。だからおそらくそれは本当の部分0です!
Iharob Al Asimi 2016

12
@ daltonfury42:浮動小数点定数のサポートを取得する必要はありません#include <float.h>(またはmath.h)。
このサイトには正直すぎる2016

2
@ daltonfury42そうです。ヘッダファイルは言語構文を変更しない、彼らは単になどの変数、関数、型、のようなものを宣言
Barmar

2
@ daltonfury42この構文の認識が、によって制御される可能性#pragmaはありますcomplex.hが、問題が発生する可能性があります。しかし、彼らはそれをこのようにしませんでした。
バーマー2016

13

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

構文カラーリングエディタで最後のものを試してください ;-)


これは、ArchLinuxを実行しているPCでGCC5.3.0を使用したときに得たものです。ここで興味のある方は私のgccの構成です。
daltonfury42 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.