Подтвердить что ты не робот

Совместимые типы и структуры в C

У меня есть следующий код:

int main(void)
{
    struct { int x; } a, b;
    struct { int x; } c;
    struct { int x; } *p;

    b = a;   /* OK */
    c = a;   /* Doesn't work */
    p = &a;  /* Doesn't work */

    return 0;
}

который не компилируется под GCC (3.4.6) со следующей ошибкой:

test.c:8: error: incompatible types in assignment
test.c:9: warning: assignment from incompatible pointer type

Теперь, из того, что я понимаю (по общему признанию, из стандарта C99), заключается в том, что a и c должны быть совместимыми типами, поскольку они соответствуют всем критериям в разделе 6.2.7, параграф 1. Я пробовал компиляция с std=c99, безрезультатно.

Предположительно, моя интерпретация стандарта неверна?

Добавление

Кстати, этот вопрос возникает из-за того, что я хотел объявить некоторые шаблонные макросы, чтобы обернуть различные типы данных без накладных расходов, чтобы объявить имена типов /typedef всюду, например. тривиальный пример:

#define LINKED_LIST(T)   \
    struct {             \
        T    *pHead;     \
        T    *pTail;     \
    }

...

LINKED_LIST(foo) list1;
LINKED_LIST(foo) list2;

...

LINKED_LIST(foo) *pList = &list1;  /* Doesn't work */
4b9b3361

Ответ 1

Глядя на черновик спецификации Я предполагаю, что вы полагаетесь на условия, которые появляются после утверждения:

Кроме того, два типа структуры, объединения или перечисления, объявленные в отдельных единицах перевода, совместимы, если их теги и члены удовлетворяют следующим требованиям...

Я думаю, что тот факт, что все они деканированы в одном файле C, означает, что они находятся в одной единицы перевода.

Полагаю, что это гарантирует, что если два файла C содержат заголовок, который объявляет тип, то экземпляры этого типа будут совместимы.

Ответ 2

struct { int x; } является тегом анонимной структуры, две анонимные структуры не могут иметь одно и то же имя, что является необходимым условием совместимости типов. Вы можете объявлять типы, совместимые с неанонимной структурой, с помощью typedef.

struct tmp { int x; }; // declare structure tag
typedef struct tmp type1;
typedef struct tmp type2; // declare 3 types compatible with struct tmp
typedef struct tmp type3; // and with each other

type1 a, b;
type2 c;
type3 *p;
b = a;
c = a;
p = &a;

Ответ 3

Совместимость структур, объединений и перечислений

Внутри одного исходного файла каждая структура или определение объединения создает новый тип, который не является ни тем же, ни совместимым с любым другой структуры или типа объединения. Однако спецификатор типа, который является ссылка на ранее определенную структуру или тип объединения одинакова тип. Тег связывает ссылку с определением и эффективно действует как имя типа. Чтобы проиллюстрировать это, только типы структур j и k совместимы в этом примере:

struct   { int a; int b; } h;
struct   { int a; int b; } i;
struct S { int a; int b; } j;
struct S k;

Совместимые структуры могут быть назначены друг другу.

Ответ 4

Интересно, что Clang дает следующее:

error: incompatible type assigning 'struct <anonymous>', expected 'struct <anonymous>'

warning: incompatible pointer types assigning 'struct <anonymous> *', expected 'struct <anonymous> *'

Кажется, что если объявляются две (или более) анонимные структуры, то компилятор делает некоторую внутреннюю магию, которая указывает, какая именно анонимная структура также передается.

Ответ 5

Учитывая пункты 6.2.7 (совместимые типы) и 6.5.16.1 (правила назначения), я понимаю то же, что и вы.

Похоже, что с вашим кодом GCC ведет себя, как если бы ваши определения структуры помечены разными тегами (что не так). В случаях, когда типы случаев не были бы совместимыми. Однако он по-прежнему выглядит как ошибка gcc.

Любая обратная связь от других компиляторов, реализующих стандарт C99?