Почему этот код C работает? - PullRequest
2 голосов
/ 04 августа 2011

РЕДАКТИРОВАТЬ: Большое спасибо за ваши ответы. Теперь я правильно понимаю!

Я пытаюсь узнать больше о C-указателях. Повозившись, я подвергаю сомнению разницу между двумя действиями, которые я использую.

Кажется, этот код работает на первый взгляд, но я не уверен, в чем разница, и если какой-то из этих двух подходов каким-то образом неверен.

Я хотел бы знать, в чем разница между двумя частями кода, когда я должен передать адрес и когда указатель на массив?

Что-то не так? Если так, что будет правильным?

с простой структурной сеткой, очень похожей на структурную сетку {int val; } (в демонстрационных целях)

Первый кусок кода. Передача адреса указателя на массив.

    void set (mygrid *grid, int foo){
        grid->bar = foo; //should this be '*grid->bar?' But this seems to work properly.
    }

    void main(){
        int i;
        int* array;
        int max = 24;

        array = malloc(sizeof(grid) * max);

        for(i = 0; i < max; i++){
            set(&array[i], 0);
        }
    }

Второй кусок кода. Я не совсем уверен, почему это работает, но компилятор не выводит никаких предупреждений. Я должен передавать указатель на начало массива, как это?

    void set(mygrid *grid, int foo){
        int i; int max = 24; //so this example code compiles :P

        for(i = 0; i < max; i++){
            grid[i].bar = foo;
        }
    }

    void main(){
        int* array;
        int max = 24;

        array = malloc(sizeof(grid) * max);
        set(array, 0); //Why not &array?
    }

Ответы [ 4 ]

2 голосов
/ 04 августа 2011

Передача массива распадается на указатель, который указывает на первый член массива, как &array[0].

1 голос
/ 04 августа 2011

Во втором примере array это просто указатель, а возвращаемое значение из malloc это просто адрес начала блока памяти, который вы получаете.

Он не имеетиспользоваться для массива;он может быть использован для хранения произвольных sizeof(int) * max байтов данных.Массив (в C) - это просто хороший способ думать и работать со сплошным блоком памяти, разделенным на части одинакового размера.

Во-вторых, вы должны понимать, как работает my_array[i].Все, что он делает, это берет адрес, где начинается ваш блок данных массива (который является фактическим значением my_array), а затем просматривает, какое значение хранится в определенном смещении оттуда.В частности, если my_array относится к (составленному) типу WhatEver, он получит доступ к данным от my_array + i*sizeof(WhatEver) до my_array + (i+1)*sizeof(WhatEver).

В связанной заметке (поскольку вы изучаете)C), настоятельно рекомендуется проверить, что возвращение от malloc не NULL, прежде чем что-либо делать с ним.

Я не гуру C, но я также пытаюсь улучшить свое понимание, так что если этоневерно, пожалуйста, оставьте комментарий или отредактируйте мой ответ, чтобы я мог учиться на своих ошибках:)

0 голосов
/ 04 августа 2011

В вашем первом куске кода

grid->bar совпадает с (*grid).bar

. и использование имени массива относится к его базовому адресу. поэтому написание array эквивалентно &array[0]

&array[i] is equivalent to array+i
array[i] is equivalent to *(array +i)

В вашем втором фрагменте кода я не понимаю, почему нет ошибки, потому что в вашем наборе функций вы не объявляете max и я тоже не вижу глобальной переменной max. также во втором фрагменте кода, который вы используете set(array,0) потому что массив уже является целочисленным указателем (см. Объявление int * array). Насколько я понимаю, mygrid - это не структура, а массив структур во втором примере

0 голосов
/ 04 августа 2011

В C массив почти такой же, как указатель.Для меня это не так удивительно, так как это один из ранних языков программирования, которые я изучал, но если вы используете язык высокого уровня, где массив - это объект другого типа, то это может показаться странным.

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