Warum ist die Aussage "2i;" KEINEN Compilerfehler verursachen?

82

Stattdessen 2*ischrieb ich nachlässig 2i:

int foo(int i)
{
    2i;
    return 2i;
}

Ich habe erwartet, dass der Compiler den Fehler abfängt. Aber das tat es nicht. Ist also 2ieine gültige Aussage in C? Wenn ja, was macht es? Verwirrt!

Ich habe mit gcc Version 5.3.0 kompiliert und hier ist die Assembly-Ausgabe:

    .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
daltonfury42
quelle
Welcher Compiler ist das?
Iharob Al Asimi
Ich arbeite nicht mit _ComplexZahlen. Nach einigem Lesen des Standards und des bereitgestellten Links denke ich, dass die Antwort von @ iharob richtig ist.
zu ehrlich für diese Seite
@Olaf Die Fastet-Fourier-Transformation im Westen fftw verwendet den _ComplexTyp. Ich fand dies heraus, als ich eine Datenverarbeitungssoftware für meine Diplomarbeit schrieb ( Physik eigentlich nicht Informatik oder ähnliches ) - ( ich musste einen Tiefpassfilter anwenden, also Faltung so schnelle Fourier-Transformation, so fftw ).
Iharob Al Asimi
@iharob: Hmm, ist das schneller als das Ffte und wenn nicht, darf ich das schneller benutzen, wenn ich im Westen lebe, aber östlich von dir? ;-) Im Ernst: danke für die Info. Wie es aussieht, unterstützt der C-Standard nicht einmal eine ähnliche einfache Notation mit C11.
zu ehrlich für diese Seite
Ein sehr gutes Beispiel für ".. nicht 'Eureka', sondern 'Das ist lustig ...'"!
usr2564301

Antworten:

107

Dies ist eine gcc- Erweiterung und 2idie imaginäre Konstante Geben Sie hier die Bildbeschreibung ein. Sie können also eine komplexe Zahl wie folgt schreiben:

#include <complex.h>

_Complex x = 4 + 5i;
Iharob Al Asimi
quelle
12
Wow, das war eine Überraschung! Können Sie mir sagen, warum es funktioniert hat, obwohl ich die Header-Datei complex.h nicht aufgenommen habe?
Daltonfury42
4
@ daltonfury42 Der Header ist für den _ComplexTyp, 2iist eine Konstante ( wie gcc es versteht ). Wenn Sie das Flag std=c99oder in std=c11Kombination mit -Wallhinzufügen, wird eine Warnung angezeigt. Es wird zwar nicht zurückgegeben, 0aber da der Rückgabetyp _Complexund der Wert sein sollten 0 + 2i, können Sie ihn nicht überprüfen printf(). Vielleicht ist das nur der eigentliche Teil 0!
Iharob Al Asimi
12
@ daltonfury42: Sie müssen #include <float.h>(oder math.h) auch keine Unterstützung für Gleitkommakonstanten erhalten .
zu ehrlich für diese Seite
2
@ daltonfury42 Das stimmt. Header-Dateien ändern nicht die Sprachsyntax, sie deklarieren nur Dinge wie Variablen, Funktionen, Typen usw.
Barmar
2
@ daltonfury42 Obwohl es möglich gewesen wäre, die Erkennung dieser Syntax durch a zu steuern #pragma, complex.hkönnte dies zu Problemen führen . Aber sie haben es nicht so gemacht.
Barmar
13

2iist eine gccErweiterung für ein komplexes ganzzahliges Literal, eine reine imaginäre Zahl, die doppelt so groß ist wie die Quadratwurzel von -1. Diese Erweiterung wird auch von unterstützt clang.

Es ist etwas überraschend, dass beim Kompilieren mit gcc 5.4.0die veröffentlichte Assembly-Ausgabe erzeugt wird:

  • Kompilieren auf http://gcc.godbolt.org/# ich einen Kompilierungsfehler Suche von gcc5.3.0: http://gcc.godbolt.org/#: error: cannot convert '__complex__ int' to 'int' in return.
  • Der angegebene Assembler-Code für die Funktion fooist falsch: Er wird nicht zurückgegeben 0. Das Konvertieren der komplexen Ganzzahlkonstante 2iin intsollte ihren Realteil zurückgeben 0.

Umgekehrt wird mit clang3.7 ohne Warnung kompiliert und der optimale Code generiert, aber natürlich nicht das, was Sie erwarten:

foo(int):                       # @foo(int)
    xorl    %eax, %eax
    retq

Diese Syntax kann in beliebiger Reihenfolge mit anderen Suffixen kombiniert werden. Das Kompilieren des folgenden Codes mit clang -Weverythinggibt mir entsprechende Warnungen 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;
}

Es erzeugt diese Ausgabe in meiner Umgebung:

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

Probieren Sie den letzten mit Ihrem Syntax-Farbeditor aus ;-)

chqrlie
quelle
Das habe ich bekommen, als ich GCC 5.3.0 auf meinem PC mit Arch Linux verwendet habe. Hier ist meine gcc-Konfiguration, wenn Sie interessiert sind.
Daltonfury42