Я не понимаю обработку одномерного массива с передачей функций - PullRequest
1 голос
/ 20 июля 2010

У меня есть массив с именем record [10], тип которого представляет собой структуру таблицы, скажем, { int, int, long, long,char}

У меня есть функция, которой я хочу передать адрес этого массива, который вызывается в цикле:

for(i = 0 ; i<10; i++)
{
    // internal resolution will be *(record + i) will fetch an address
    function(record[i]);
}

Я не понимаю, почему это не работает.Я знаю, что это связано с основами.

Он начал работать с

for(i = 0 ; i<10; i++)
{
    // then why do I need to pass this address of address here 
    function(&record[i]); 
}

Ответы [ 5 ]

8 голосов
/ 20 июля 2010

*(record + i) на самом деле не является адресом. record - это адрес, как и (record + i), но *(record + i) - это значение , сохраненное по адресу, представленному (record + i). Следовательно, вызов function(record[i]) аналогичен function(*(record + i)), который передаст значение элемента массива функции, а не указателю.

Синтаксис &record[i] не принимает адрес адреса. Он принимает адрес record[i], который является объектом. Скобки имеют более высокий приоритет, чем амперсанд, поэтому &record[i] эквивалентно &(record[i]). Вы можете думать об этом как о расширении до &(*(record + i)), а затем об упрощении до (record + i).

Обновление: Чтобы ответить на ваш вопрос из комментария, массив «разлагается» на указатель, если вы сами ссылаетесь на имя массива. Если вы добавите квадратные скобки [], вы получите значение из массива. Итак, для вашего примера, скажем, у вас есть массив структур:

struct A {
    ...
    char abc[10];
    ...
} record[10];

Тогда вы бы получили:

  • record[i] - объект типа struct A из массива record
  • record[i].abc - массив abc внутри определенного объекта record, распадающийся на указатель
  • record[i].abc[k] - конкретный символ из строки
  • &record[i].abc[0] - один из способов создания указателя на строку

Нотация record[i]->abc, которую вы упоминаете в комментарии, не может быть использована, поскольку record[i] является объектом, а не указателем.

Обновление 2: Что касается вашего второго комментария, те же правила, описанные выше, применяются независимо от того, как вы вкладываете массив в структуру (и обращаетесь ли вы к этой структуре напрямую или через указатель). Доступ к массиву с использованием записи arrayname[index] даст вам элемент из массива. Доступ к массиву с использованием нотации arrayname (то есть с использованием самого имени массива) даст вам указатель на первый элемент в массиве. Если вам нужна более подробная информация об этом явлении, вот пара ссылок, которые объясняют массивы и то, как их имена могут распадаться на указатели:

1 голос
/ 20 июля 2010

Вы говорите две разные вещи в своем вопросе.Во-первых, вы говорите, что хотите передать адрес массива, но в коде вы пытаетесь передать адрес определенного элемента.Одной из особенностей C является то, что массив автоматически превращается в указатель на первый элемент массива, когда вы используете его в определенных контекстах.Это означает, что эти два вызова эквивалентны на 100%:

function(array);
function(&array);

Чтобы получить адрес определенного элемента массива, вы можете сделать две вещи.Один из них, как вы показали выше:

function(&array[10]);

А второй просто сделайте арифметику указателя напрямую:

function(array + 10);

В первом случае требуется &, посколькукак вы упомянули в своем вопросе, [] вызывает разыменование указателя - & отменяет эту операцию.То, что вас смущает, так это настоящая семантика операции [].Он выполняет арифметику с указателями, а затем разыменовывает результат - вы не получаете адрес из этого.Вот тут и приходит & (или просто напрямую array + 10).

0 голосов
/ 20 июля 2010

Ваша функция ожидает указатель на структуру. Этот аргумент может быть отдельным экземпляром этой структуры или элементом массива структуры структуры. Как

struct myStruct {
     int a, b;
     long cL, dL;
     char e;
} struc1, struc2, record[20];

и прототип функции будет

function( struct myStruct *ptr);

Теперь вы можете передать структуру в функцию:

function( &struct1 );
// or
function( &record[ index] );

Теперь ваша путаница возникает из-за неправильного представления о том, что синтаксис array[i] также может рассматриваться как указатель, как мы можем делать с именем array.

record - имя массива - дает адрес первого члена массива (указатели также указывают на адреса памяти), следовательно, его можно передать функции. Но record[index], это другое.

На самом деле, когда мы пишем record[ index], это дает нам значение, помещенное туда, которое не является указателем. Следовательно, ваша функция, которая принимает указатель, не принимает его.

Чтобы сделать его приемлемым для функции, вам нужно будет передать адрес элементов массива, т.е.

function( &record[ index ] );

Здесь & оператор дает адрес элементов массива.

Также вы можете использовать:

function( record + index  );

Здесь, как мы знаем, record - это адрес первого элемента, и когда мы добавляем в него index, он дает адрес соответствующего элемента, используя арифметику указателей.

Надеюсь, это было полезно.

0 голосов
/ 20 июля 2010

Скорее всего, подпись вашей функции

void function(table *); // argument's type is pointer to a table 

Когда вы передаете record[i], вы передаете объект таблицы. Чтобы передать указатель на таблицу, вы должны передать &record[i], как вы это сделали.

0 голосов
/ 20 июля 2010

Вы передаете по значению, которое означает, что копия переменной отправлена ​​в функцию. Во втором случае вы проходите по ссылке.

Во втором случае вы напрямую изменяете содержимое по адресу массива плюс индекс.

Проверьте этот простой пример , чтобы узнать точную разницу.

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