Как скомпилировать код C с анонимными структурами / объединения?

Я могу сделать это в c ++/g ++:

struct vec3 { 
    union {
        struct {
            float x, y, z;
        }; 
        float xyz[3];
    }; 
};

Затем

vec3 v;
assert(&v.xyz[0] == &v.x);
assert(&v.xyz[1] == &v.y);
assert(&v.xyz[2] == &v.z);

будет работать.

Как каждый делает это в c с gcc? Я имею

typedef struct {
    union {
        struct {
            float x, y, z;
        };
        float xyz[3];
    };
} Vector3;

Но я получаю ошибки все вокруг, конкретно

line 5: warning: declaration does not declare anything
line 7: warning: declaration does not declare anything
64
задан Ciro Santilli 新疆改造中心法轮功六四事件 15 September 2014 в 19:13
поделиться

7 ответов

согласно http://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html#Unnamed-Fields

-fms-extensions включит функцию, которую хотите вы (и я).

50
ответ дан 24 November 2019 в 15:49
поделиться

Анонимные союзы - особенность языка Си++. Язык Си не имеет анонимных союзов.

Анонимных структур не существует ни в Си, ни в Си++.

Декларация, которую Вы представили в своем вопросе, может быть скомпилирована с компилятором GCC C++, но это будет просто специфическое для компилятора расширение, которое не имеет никакого отношения ни к стандартному Си, ни к стандартному Си++.

Кроме того, независимо от того, как Вы его реализуете, ни язык Си, ни язык Си++ не гарантируют, что Ваши утверждения будут иметь место.

.
8
ответ дан 24 November 2019 в 15:49
поделиться

(Этот ответ относится к C99, а не к C11).

C99 не имеет анонимных структур или союзов. Вы должны назвать их:

typedef struct {
    union {
        struct {
            float x, y, z;
        } individual;
        float xyz[3];
    } data;
} Vector3;

И затем вы должны использовать имя при доступе к ним:

assert(&v.data.xyz[0] == &v.data.individual.x);

В этом случае, поскольку ваша структура верхнего уровня имеет один элемент типа union, вы можете упростить это:

typedef union {
    struct {
        float x, y, z;
    } individual;
    float xyz[3];
} Vector3;

и доступ к данным теперь становится:

assert(&v.xyz[0] == &v.individual.x);
32
ответ дан 24 November 2019 в 15:49
поделиться

Анонимные союзы не поддерживаются в C.

Также обратите внимание, что если вы объявите это так:

typedef struct {
    union {
        struct {
            float x, y, z;
        } individual;
        float xyz[3];
    } data;
} Vector3;

Doing

Vector3 v;
v.data.xyz[0] = 5;

float foo = v.data.individual.x;

- это неопределенное поведение. Вы можете получить доступ только к последнему назначенному члену профсоюза. В вашем случае, использование объединения - неправильная и плохая практика кодирования, так как зависит от многих вещей, которые не указаны в стандарте (padding...).

В C вы предпочтете что-то вроде этого:

typedef struct {
    float v[3];
} Vec3;

И если вы не хотите использовать v[x], вы можете подумать:

#define X(V) ((V).v[0])

Vec3 v;
X(v) = 5.3;
printf("%f\n", X(v));
2
ответ дан 24 November 2019 в 15:49
поделиться

Есть мосты на AppleScript из Ruby, Objective-C и другие.

-121--3294805-

Я могу сделать это в GCC без предупреждения

typedef union {
    struct { // human-friendly access
        float x;
        float y;
        float z;
        float w;
    };
    float xyz[3];
    struct { // human-friendly access
        float r;
        float g;
        float b;
        float a;
    };
    float rgb[3];
} Vector4f;

int main()
{
    Vector4f position, normal, color;
    // human-friendly access
    position.x = 12.3f;
    position.y = 2.f;
    position.z = 3.f;
    position.w = 1.f;

    normal.x = .8f;
    normal.y = .9f;
    normal.z = .1f;
    normal.w = 1.f;

    color.r = 1.f;
    color.g = .233f;
    color.b = 2.11f;
    color.a = 1.1f;

    // computer friendly access
    //some_processor_specific_operation(position.vec,normal.vec);
    return 0;
}

C: \> GCC VEC.c -Wall

C: \> GCC --version GCC (GCC) 4.4.0 Copyright (C) 2009 Free Software Foundation, Inc. Это бесплатное программное обеспечение; Смотрите источник для копирования условий. Здесь нет гарантия; даже для товаров или пригодности для определенной цели.

3
ответ дан 24 November 2019 в 15:49
поделиться

Диалект GNU языка C поддерживает анонимные структуры / объединения, но по умолчанию GCC компилируется с использованием некоего стандартного языка C. Чтобы использовать диалект GNU, введите «-std = gnu99» в командную строку.

0
ответ дан 24 November 2019 в 15:49
поделиться

Неопознанные члены структуры, не являющиеся стандартом ANSI / ISO C99, объясняют это, но я нахожу забавную вещь, когда на некоторых портах версий GNU C Compiler 2.xx использование неопознанных членов структуры работает, он их находит, не говорит что-то вроде «x не является членом union \ struct y, что такое x?», в других случаях это старый «x is undefined», «x не является членом struct», черт возьми, я клянусь, что видел «указатель на unknown "некоторое время назад, в связи с этим.

Итак, я профессионально согласился бы со всеми остальными в этом вопросе и просто дал бы элементу struct \ union идентификатор или, в случае UNION, тщательно переупорядочил код, чтобы объединение закончилось идентифицированным членом идентифицированной структуры и члены, которые были встроены в неопознанную структуру исходного объединения, становятся членами идентифицированной структуры и тщательно используются с идентифицированным членом объединения. Но в тех случаях, когда последний метод не был бы работоспособной заменой, я бы просто присвоил раздражающей структуре идентификатор и двинулся дальше.

0
ответ дан 24 November 2019 в 15:49
поделиться