Составные литералы в MSVC - PullRequest
8 голосов
/ 06 октября 2010

В GCC я могу сделать это:

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

где:

struct CachedPath
{
    Ino ino;
};

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

MSVC выдает следующую ошибку для такого рода приведений:

error C2143: syntax error : missing ';' before '{'

Как я могу сделать это в MSVC? Далее обратите внимание, что код был преобразован из C99, где я использовал назначенные инициализаторы для этого, а затем преобразовал его аналогично. Любая ясность в отношении того, как эти различные функции связаны между C99 и MSVC / GCC реализациями C ++, приветствуется.

Ответы [ 4 ]

12 голосов
/ 06 октября 2010

Конструкция (Type){initialisers} не является операцией приведения, но это синтаксическая конструкция составного литерала .Это конструкция C99, которую GCC также поддерживает в своем компиляторе C ++ как расширение.Насколько я могу определить, составные литералы не поддерживаются MSVC ни в режиме C, ни в C ++.

Альтернативы для этой конструкции:

  • Явное объявление и инициализация временного объекта.нужного типа структуры и используйте его вместо составного литерала в присваивании
  • Вместо того, чтобы выполнять одно присваивание с составным литералом, используйте отдельное присваивание для каждого отдельного члена.
4 голосов
/ 06 октября 2010

MSVC не соответствует C99 и только слабо соответствует предыдущим версиям стандарта C. Я не знаю способа сделать то, что вы хотите синтаксически с MSVC, но тот же эффект можно получить, используя static const структуры вместо анонимных составных литеральных констант и локальные struct переменные, которые инициализируются правильные значения вместо анонимных составных литералов, которые не являются постоянными.

Идея этого подхода заключается в том, что составной литерал C99 (по крайней мере, почти) эквивалентен локальной переменной того же типа в той же области видимости, инициализированной содержимым фигурных скобок. Использование структур static const в случае, когда данные постоянны, является просто оптимизацией (скорее всего, код будет меньше / быстрее, чем составной буквальный подход C99).

1 голос
/ 06 октября 2010

MSVC представляет собой набор стандартов и не полностью совместим с большинством из них, поэтому вам, вероятно, потребуется использовать инициализатор / конструктор по умолчанию, например (C ++):

#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)
    {
    }
};
0 голосов
/ 16 ноября 2018

Visual Studio, начиная с VS2013, поддерживает составные литералы и назначенные инициализаторы. Какие функции C99 доступны в компиляторе MS Visual Studio?

Пример:

// main.c
#include <stdio.h>

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]);
    }
}
...