9 Stimmen

Zusammengesetzte Literale und funktionsähnliche Makros: Fehler in gcc oder dem C-Standard?

In C99 haben wir zusammengesetzte Literale, die an Funktionen wie in übergeben werden können:

f((int[2]){ 1, 2 });

Wenn jedoch f keine Funktion, sondern ein funktionsähnliches Makro ist, scheitert der Gcc daran, weil der Präprozessor es nicht als ein Argument, sondern als zwei Argumente parst, " (int[2]){ 1 " und " 2 } ".

Ist dies ein Fehler in gcc oder in der C-Norm? Wenn es das letztere ist, schließt das so ziemlich jede transparente Verwendung von funktionsähnlichen Makros aus, was ein großer Fehler zu sein scheint...

Editar: Als Beispiel würde man erwarten, dass das folgende Programmfragment konform ist:

fgetc((FILE *[2]){ f1, f2 }[i]);

Da aber fgetc als Makro implementiert werden könnte (auch wenn es erforderlich wäre, sein Argument zu schützen und es nicht mehr als einmal auszuwerten), wäre dieser Code tatsächlich falsch. Das scheint mir überraschend zu sein.

10voto

Steve Jessop Punkte 264569

Dieser "Fehler" ist seit C89 in der Norm enthalten:

#include <stdio.h>

void function(int a) {
    printf("%d\n", a);
}

#define macro(a) do { printf("%d\n", a); } while (0)

int main() {
    function(1 ? 1, 2: 3); /* comma operator */
    macro(1 ? 1, 2: 3);    /* macro argument separator - invalid code */
    return 0;
}

Ich habe nicht wirklich durch den Standard gesehen, um diesen Parse zu überprüfen, ich habe gcc's Wort für sie genommen, aber informell die Notwendigkeit für eine passende : zu jeder ? übertrumpft sowohl den Vorrang der Operatoren als auch die Syntax der Argumentliste, damit die erste Anweisung funktioniert. Bei der zweiten Anweisung ist das nicht der Fall.

6voto

James McNellis Punkte 337231

Dies ist nach dem C-Standard, ähnlich wie in C++, das Folgende ein Problem ist:

f(ClassTemplate<X, Y>) // f gets two arguments:  'ClassTemplate<X' and 'Y>'

Wenn es in C99 erlaubt ist, dort einige zusätzliche Klammern hinzuzufügen, können Sie diese verwenden:

f(((int[2]){ 1, 2 }));
  ^                ^

Die Regel, die dieses Verhalten spezifiziert, aus C99 §6.10.3/11, lautet wie folgt:

Die durch die äußerste übereinstimmende Klammer begrenzte Folge von Vorverarbeitungs-Token begrenzt wird, bildet die Liste der Argumente für das funktionsähnliche Makro.

Die einzelnen Argumente innerhalb der Liste werden durch Komma-Vorsatzzeichen getrennt, aber Komma-Vorsatzzeichen zwischen passenden inneren Klammern trennen die Argumente nicht.

1voto

Jerry Coffin Punkte 452852

Soweit es sich überhaupt um einen Fehler handelt, liegt es am Standard, nicht am gcc (d.h. in dieser Hinsicht glaube ich, dass der gcc tut, was der Standard verlangt).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X