несовместимые типы структур в приведениях / назначениях? - PullRequest
5 голосов
/ 25 октября 2011

Это продолжение этого вопроса .

Я стараюсь избегать использования явного typedef для копирования одного массива в другой через приведение типаthis:

#include <stdio.h>

int main(void)
{
  int i;
  int dst[] = { 10, 20, 30 }, src[] = { 1, 2, 3 };

  *(struct{int _[3];}*)dst = *(struct{int _[3];}*)src;

  for (i = 0; i < 3; i++) printf("%d\n", dst[i]);
  return 0;
}

С gcc я получаю arrcpy.c:8: error: incompatible types in assignment, однако с Open Watcom он компилируется нормально (и работает, как я ожидаю, печатая с 1 по 3).

Является лиПоведение gcc по стандарту или нет?Если это так, какова соответствующая глава и раздел?Я не могу понять, почему два идентичных определения типа struct{int _[3];} не одинаковы (или совместимы) в глазах gcc.

EDIT : я прекрасно знаю, что это плохой стиль кодирования,Вопрос в другом.Мне любопытно, есть ли логическое обоснование поведения gcc, если это законно.

Ответы [ 4 ]

6 голосов
/ 25 октября 2011

Правильное поведение gcc, типы - это две несвязанные неназванные структуры. Каждая из этих структур, имея одинаковую структуру памяти, имеет разные имена. Если вы действительно хотите это сделать, используйте typedef.

1 голос
/ 25 октября 2011

Два определения struct несовместимы:

Начиная с C99 6.2.7:

Два типа имеют совместимый тип, если их типы совпадают.Дополнительные правила определения совместимости двух типов описаны в 6.7.2 для спецификаторов типов, в 6.7.3 для классификаторов типов и в 6.7.5 для деклараторов.Более того, два типа структуры, объединения или перечисления , объявленные в отдельных единицах перевода , совместимы, если их теги и члены удовлетворяют следующим требованиям ...

Типы не являютсятак же.Если бы они были объявлены в отдельных единицах перевода, они были бы совместимы, однако.

Однако, даже если они были совместимы, ваш код все равно вызывал бы неопределенное поведение, по крайней мере по двум причинам:

  1. Используется имя "_", которое зарезервировано.
  2. Доступ к объектам другого типа (кроме структур через указатели на символы, объединения и т. Д.) Запрещен.
1 голос
/ 25 октября 2011

По сути, эквивалентность типов не является структурной эквивалентностью в C. В C используется система номинативных типов .

В соответствии с § 6.7.2.1-7 C99:

Наличие списка struct-объявление-list в спецификаторе struct-or-union объявляет новый тип внутри единицы перевода. Структура-объявление-список представляет собой последовательность объявлений для членов структуры или объединения. Если список объявляемых структур не содержит именованных членов, поведение не определено. Тип является неполным до тех пор, пока после}, который завершает список.

struct-declaration-list и struct-or-union-specifier взяты из грамматики C (§ 6.7.2.1):

struct-or-union-specifier:
    struct-or-union identifier<sub>opt</sub> { struct-declaration-list }

struct-or-union:
    <b>struct</b>
    <b>union</b>

Даже если две разные структуры имеют одинаковую структуру памяти, они бывают разных типов.

Если вы хотите избежать загрязнения глобального пространства имен, вы можете объявить структуру локально для функции, в которой вы ее используете.

#include <stdio.h>

int main(void) {
    // struct T is only visible in main()
    struct T {int _[3];};
    int i;
    int dst[] = { 10, 20, 30 }, src[] = { 1, 2, 3 };

    *(struct T*)dst = *(struct T*)src;

    for (i = 0; i < 3; i++) printf("%d\n", dst[i]);

    return 0;
}

void fails(void) {
    // will cause a compilation error, because struct T is an incomplete type.
    struct T t;
}
1 голос
/ 25 октября 2011

Почему бы вам просто не использовать memcpy?

#include <stdio.h>
#include <string.h>

int main(void)
{
  int i;
  int dst[] = { 10, 20, 30 }, src[] = { 1, 2, 3 };

  memcpy(dst, src, 3 * sizeof(int));

  for (i = 0; i < 3; i++) printf("%d\n", dst[i]);
  return 0;
}

или по размеру вместо 3: sizeof(dst)/sizeof(dst[0])

РЕДАКТИРОВАНИЕ: С вашим редактированием я могу только предположить, что, как и в случае outis 'answer , компилятор рассматривает два определения структур как два разных типа структур. Даже если они могут содержать одни и те же данные, они бывают двух разных типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...