У меня есть следующая программа. Тем не менее, я не могу понять, почему я должен передать адрес массива. Когда они оба указывают на один и тот же адрес. Это адрес первого элемента массива int.
Я получаю предупреждение, когда пытаюсь выполнить «назначение из несовместимого типа указателя»:
ptr = var;
Полный исходный код:
void print_values(int (*ptr)[5])
{
size_t i = 0;
for(i = 0; i < 5; i++) {
printf("%d: [ %d ]\n", i, (*ptr)[i]);
}
}
int main(void)
{
/* declare a pointer to an array integers */
int (*ptr)[5] = NULL;
/* array of integers */
int var[] = {1, 2, 3, 4, 5};
/* assign the address of where the array is pointing to (first element) */
ptr = &var;
/* Both are pointing to the exact same address */
printf("var [ %p ]\n",(void*)var);
printf("&var [ %p ]\n", (void*)&var);
print_values(ptr);
return 0;
}
Я компилирую код с gcc 4.4. 4 c89 -Wall -Wextra -O0
Это чисто типовая проблема.
В большинстве контекстов выражений имя массива (например, var
) распадается на указатель на начальный элемент массива, а не на указатель на массив. [Обратите внимание, что это не означает, что var
является указателем - это в значительной степени не указатель - он просто ведет себя как указатель на первый элемент массива в большинстве выражений.]
Это означает, что в выражении var
обычно распадается на указатель на int
, а не на указатель на массив int
.
Поскольку операнд оператора адресации ( &
) является одним контекстом, к которому это правило распада не применяется (другой является операндом оператора sizeof
) . В этом случае тип & var
является производным непосредственно от типа var
, поэтому типом является указатель на массив 5 int
.
Да, указатели имеют одинаковое значение адреса (адрес первого элемента массива - это адрес самого массива), но они имеют разные типы ( int *
vs int (* ) [5]
) поэтому несовместимы в назначении.
ИСО / МЭК 9899: 1999 6.3.2.1/4:
За исключением случаев, когда это операнд оператора
sizeof
или унарный оператор&
, либо строка литерал, используемый для инициализации массива, выражение типа «массив тип » преобразуется в выражение типа «указатель на тип», которое указывает на начальный элемент объекта массива и не является lvalue . ...
var
сам по себе является (* int)
, указывающим на первый элемент в вашем массиве. Указатели и массивы в C очень похожи. Измените int (* ptr) [5] = NULL;
на int * ptr = NULL;
и ptr = & var;
на ptr = var;
Язык Си является сильно типизированным языком. Когда функция ожидает параметр типа int *
, вы должны передать аргумент типа int *
. Не double *
, не char *
, а int *
. Даже если фактический числовой адрес в этих double *
или char *
"такой же", как тот, который вы хотите передать, это ничего не меняет - вы все равно должны передать int *
. Язык запрещает передавать значение неправильного типа.
Именно это и происходит в вашем случае. Функция принимает параметр типа int (*)[5]
. Это означает, что вы должны передать аргумент этого типа. Передача int *
вместо этого не допускается. Одинаков ли адрес, не имеет значения.
Насколько я могу судить, вы назначаете указатель массива ( var
) указателю, который указывает на указатель массива ( (* ptr) [5]
), поэтому вы и получили это предупреждение.
Вместо этого попробуйте использовать
int *ptr = NULL;