8 Stimmen

Zusammengesetzte Literale in MSVC

Im GCC bin ich in der Lage, das Folgende zu tun:

(CachedPath){ino}
inode->data = (struct Data)DATA_INIT;

wo:

struct CachedPath
{
    Ino ino;
};

typedef int8_t Depth;
struct Data
{
    Offset size;
    Blkno root;
    Depth depth;
};
#define DATA_INIT {0, -1, 0}

MSVC gibt für diese Art von Umwandlungen den folgenden Fehler aus:

Fehler C2143: Syntaxfehler : ';' fehlt vor '{'

Wie kann ich das in MSVC machen? Weiterhin beachten Sie, dass der Code von C99 konvertiert wurde, wo ich für dies benannte Initialisierer verwendet habe, und dann ähnlich umgewandelt habe. Jegliche Klarheit darüber, wie diese verschiedenen Funktionen zwischen C99 und den Implementierungen von MSVC/GCC von C++ zusammenhängen, wird geschätzt.

14voto

Bart van Ingen Schenau Punkte 15048

Der Aufbau (Typ){Initialisierer} ist keine Cast-Operation, sondern der syntaktische Aufbau eines Compound Literal. Dies ist ein Konstrukt aus C99, das auch vom GCC in seinem C++-Compiler als Erweiterung unterstützt wird. Soweit ich feststellen kann, werden Compound Literals bis einschließlich MSVC 2012 in keinem der Modi (C oder C++) unterstützt. Die Unterstützung im C-Modus wurde später, in MSVC 2013, eingeführt. Im C++-Modus wird es nach wie vor nicht unterstützt, und ich glaube, dass es unwahrscheinlich ist, dass die Unterstützung hinzugefügt wird.

Für MSVC 2012 und älter sind die Alternativen für dieses Konstrukt:

  • Deklarieren und Initialisieren Sie explizit ein temporäres Objekt des gewünschten Strukturtyps und verwenden Sie dies anstelle des Compound Literals bei der Zuweisung.
  • Verwenden Sie anstelle einer einzelnen Zuweisung mit dem Compound Literal separate Zuweisungen für jedes einzelne Element.

3voto

MSVC entspricht nicht C99 und nur locker den früheren Versionen des C-Standards. Ich weiß keinen Weg, um das, was du willst, syntaktisch mit MSVC zu erreichen, aber der gleiche Effekt kann erzielt werden, indem man static const Strukturen anstelle von anonymen Literalen verwendet und lokale struct Variablen, die mit den richtigen Werten initialisiert sind, anstelle von anonymen Literalen, die nicht konstant sind.

Die Idee hinter diesem Ansatz ist, dass ein C99 Compound-Literal (zumindest fast) äquivalent zu einer lokalen Variable des gleichen Typs im gleichen Bereich ist, die mit dem Inhalt der Klammern initialisiert ist. Die Verwendung von static const Strukturen in den Fällen, in denen die Daten konstant sind, dient lediglich der Optimierung (sie wird wahrscheinlich kleinere/schnellere Code als der C99 Compound-Literal-Ansatz erzeugen).

2voto

infval Punkte 128

Visual Studio unterstützt seit VS2013 Compound-Literale und Designated-Initialisierer. Welche C99-Features sind im MS Visual Studio-Compiler verfügbar?

Beispiel:

// main.c
#include 

void func(int(*array)[3]);

int main()
{
    // Designated initializers

    int a[6] = { [4] = 29, [2] = 15 }; // [0, 0, 15, 0, 29, 0]

    struct point { int x, y; };
    struct point p = { .y = 13, .x = 27 }; // x = 27, y = 13

    union foo { int i; double d; };
    union foo f = { .d = 4 }; // d = 4.0

    struct point ptarray[5] = { [2].y = 34, [2].x = 42, [0].x = 58 };
    // (58 0), (0 0), (42 34), (0 0), (0 0)

    // Compound literals

    int *a1 = NULL;
    a1 = (int[6]) { [4] = 29, [2] = 15 }; // [0, 0, 15, 0, 29, 0]

    struct point p1;
    p1 = (struct point) { .y = 13, .x = 27 }; // x = 27, y = 13

    union foo f1;
    f1 = (union foo) { .d = 4 }; // d = 4.0

    struct point *ptarray1 = NULL;
    ptarray1 = (struct point[5]) { [2].y = 34, [2].x = 42, [0].x = 58 };
    // (58 0), (0 0), (42 34), (0 0), (0 0)

    int *p2 = NULL;
    p2 = (int[2]) { -1 };
    p2 = (int[]) { -73, 89, 92 };
    func(&(int[]) { -73, 89, 92 });

    return 0;
}

void func(int(*array)[3])
{
    for (int i = 0; i < 3; i++) {
        printf("%d ", (*array)[i]);
    }
}

0voto

Necrolis Punkte 25132

MSVC ist eine Mischung aus Standards und entspricht den meisten von ihnen nicht vollständig, daher müssen Sie wahrscheinlich einen Standard-Initialisierer/Konstruktor verwenden, wie folgt (C++-Art):

#define DATA_INIT 0,-1,0
inode->data = Data(DATA_INIT);

struct Data
{
    Offset size;
    Blkno root;
    Depth depth;

    Data(Offset size, Blkno root, Depth depth) : size(size), root(root), depth(depth)
    {
    }
};

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