Почему я не могу назначить массив указателю непосредственно в C?

У меня есть следующая программа. Тем не менее, я не могу понять, почему я должен передать адрес массива. Когда они оба указывают на один и тот же адрес. Это адрес первого элемента массива 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

11
задан P Shved 17 August 2010 в 16:35
поделиться

4 ответа

Это чисто типовая проблема.

В большинстве контекстов выражений имя массива (например, var ) распадается на указатель на начальный элемент массива, а не на указатель на массив. [Обратите внимание, что это не означает, что var является указателем - это в значительной степени не указатель - он просто ведет себя как указатель на первый элемент массива в большинстве выражений.]

Это означает, что в выражении var обычно распадается на указатель на int , а не на указатель на массив int .

Поскольку операнд оператора адресации ( & ) является одним контекстом, к которому это правило распада не применяется (другой является операндом оператора sizeof ) . В этом случае тип & var является производным непосредственно от типа var , поэтому типом является указатель на массив 5 int .

Да, указатели имеют одинаковое значение адреса (адрес первого элемента массива - это адрес самого массива), но они имеют разные типы ( int * vs int (* ) [5] ) поэтому несовместимы в назначении.

ИСО / МЭК 9899: 1999 6.3.2.1/4:

За исключением случаев, когда это операнд оператора sizeof или унарный оператор & , либо строка литерал, используемый для инициализации массива, выражение типа «массив тип » преобразуется в выражение типа «указатель на тип», которое указывает на начальный элемент объекта массива и не является lvalue . ...

20
ответ дан 3 December 2019 в 03:16
поделиться

var сам по себе является (* int) , указывающим на первый элемент в вашем массиве. Указатели и массивы в C очень похожи. Измените int (* ptr) [5] = NULL; на int * ptr = NULL; и ptr = & var; на ptr = var;

3
ответ дан 3 December 2019 в 03:16
поделиться

Язык Си является сильно типизированным языком. Когда функция ожидает параметр типа int *, вы должны передать аргумент типа int *. Не double *, не char *, а int *. Даже если фактический числовой адрес в этих double * или char * "такой же", как тот, который вы хотите передать, это ничего не меняет - вы все равно должны передать int *. Язык запрещает передавать значение неправильного типа.

Именно это и происходит в вашем случае. Функция принимает параметр типа int (*)[5]. Это означает, что вы должны передать аргумент этого типа. Передача int * вместо этого не допускается. Одинаков ли адрес, не имеет значения.

4
ответ дан 3 December 2019 в 03:16
поделиться

Насколько я могу судить, вы назначаете указатель массива ( var ) указателю, который указывает на указатель массива ( (* ptr) [5] ), поэтому вы и получили это предупреждение.

Вместо этого попробуйте использовать

int *ptr = NULL;
1
ответ дан 3 December 2019 в 03:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: