Влияние размера массива int на эквивалентность типов

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

Он описывает «эквивалентность типов» C как:

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

Так что, если у меня есть два массива разного размера, но одного и того же базового типа:

typedef int A1[10];  
typedef int A2[20];

Поскольку все, что мне нужно, — это структурная эквивалентность, можно ли считать их структурно эквивалентными? В C является ли размер набора индексов частью типа массива или нет?


person Mithrax    schedule 14.04.2009    source источник


Ответы (3)


Нет, они не.

Вы можете попробовать sizeof(A1) и sizeof(A2) и увидеть, что они разные.

person mmx    schedule 14.04.2009

Нет, они не одного типа.

В C вы не получите ошибку, но в C++, если вы попытаетесь, вы получите что-то вроде ошибки:

ошибка C2440: «инициализация»: невозможно преобразовать «int () [1024]» в «int () [512]»

Вот пример кода

int x[1024];
int y[512];
/*Create a pointer int[1024] type*/
int (*px)[1024] = &x;
/*Create a pointer int[512] type*/
int (*py)[512] = &y;

int (*py2)[512] = &x; /*<---compiling error in C++ but allowed in C even know it's wrong*/

Даже зная, что последняя строка разрешена в C, 2 типа считаются разными. Кроме того, массив — это не то же самое, что указатель на массив, но, как вы можете видеть, объявления типов отличаются.

person Brian R. Bondy    schedule 14.04.2009
comment
Но в моей книге говорится, что указатели структурно эквивалентны в C. Итак, если массив является указателем на n элементов, тогда они не будут структурно эквивалентны? - person Mithrax; 14.04.2009
comment
Массив не является указателем — в некоторых ситуациях он может разлагаться на указатель, но он не эквивалентен указателю. - person 1800 INFORMATION; 14.04.2009

В исходном коде в некоторых контекстах переменные разных типов совместимы в заданном выражении, и компилятор вызовет достаточно магии, чтобы сделать правильную/ожидаемую вещь, например, передав массив в качестве аргумента функции, ожидающей указатель. Однако это не означает, что расположение памяти у них совместимо. См. Вопрос Указатель против массива в C, нетривиальная разница где я пропустил это.

Я не совсем уверен, что ваша книга подразумевает под «структурной эквивалентностью», но интересно, может быть, это относится к целочисленному продвижению по умолчанию (но, похоже, также включает массивы?). Но в любом случае целочисленное продвижение — очень важный вопрос, и вы должны потратить время на его понимание. Приведенный ниже printf должен выполняться в соответствии с этими правилами:

unsigned int i = 0;
if (i < -1) {
        printf("This line is printed!\n");
}

стандарт C (ISO/IEC 9899:1990) содержит раздел с заголовок «обычные арифметические преобразования», определяющий поведение. Стандарт не находится в свободном доступе (наоборот, он продается довольно дорого, поскольку цены на стандарты ISO указаны за страницу...), но если вы будете искать этот термин, вы сможете найти полезную информацию или цитаты. Некоторые из черновиков стандартов находятся в свободном доступе, однако вызывают у них большое недоверие, поскольку вы точно не знаете, что было изменено в окончательный стандарт.

person hlovdal    schedule 15.04.2009
comment
Действительно? У меня с этим проблем нет, но в любом случае у вас должна быть возможность поиска по названию. - person hlovdal; 15.04.2009