Передача адреса массива в качестве параметра функции - PullRequest
3 голосов
/ 11 июля 2011

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

void foo(char b[2]);
char a[2] = {1, 2};
foo(a);   // I always assumed that this would pass the entire array to be
          // duplicate in stack, guess I was wrong all this while
          // Instead the address of the array was passed

void foo(char b[2])
{
   // Value of b[0], b[1]?
   // Does this mean :   1) b[0] == &a[0]?
   //                or  2) b[0] == &a[0+2]?
   // Compiler didn't complain, so I assume this is a valid syntax
}

Ответы [ 6 ]

6 голосов
/ 11 июля 2011

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

При вводе в функцию значения каждогоВыражение аргумента должно быть преобразовано в тип его соответствующего параметра, как если бы оно было присвоено параметру. Выражения массива и указатели функций в качестве аргументов преобразуются в указатели перед вызовом.Объявление параметра как «массив типа» должно быть изменено на «указатель на тип, »

Это, по сути, означает, что в объявлении вашей функции это эквивалентно использованию

void foo(char b[2]); или void foo(char b[]); или void foo(char *b)

`

0 голосов
/ 11 июля 2011

Я должен сделать исправление: адрес массива не передается - это адрес первого элемента массива. Самый простой способ выразить это:

В C значение массива является указателем на его первый элемент.

Если вы работаете с массивами массивов, вам необходимо предоставить информацию о размерах массивов после первого разыменования:

// either the following or: void foo(char param[][30][20])
void foo(char (*param)[30][20])
{
    // ...
}


int main(void)
{
    // bar is an array of 10 arrays of 30 arrays of 20 chars.
    // its value's TYPE is 'pointer to an array of 30 arrays of 20 chars,
    // which is what foo above requires.
    char bar[10][30][20];

    foo(bar);

}
0 голосов
/ 11 июля 2011

b[0] = &a[0] если вы введете foo(a) в качестве аргумента.

Если вы передадите foo((a+1)), то b[0] = &a[1] (вы не должны этого делать, поскольку b[1] будет неопределенным) и т. Д.на.

0 голосов
/ 11 июля 2011
  1. Когда вы объявляете массив как параметр функции, он обрабатывается как указатель. Ваш foo полностью идентичен

    void foo(char *b)
    {
        ...
    }
    
  2. Массивы распадаются на указатели. Другими словами, в некоторых случаях (например, sizeof(a)) a является массивом, но в других, где ожидается указатель, имя a означает адрес a[0].

0 голосов
/ 11 июля 2011

Это то же самое, что и следующее:

// The array "char b[2]" "decays" to a pointer "char *b"
void foo(char *b)
{
    // b[0] == a[0]
    // also, b == a (two addresses, both the same)
}

Вы можете прочитать о том, как массивы и указатели в C ведут себя очень похожим образом (но не точно то же самое). Массивы распадаются на указатели, если они являются аргументами функции (но не где-либо еще). Реальный улов здесь заключается в том, что в 64-битной системе sizeof(b) == 8 и sizeof(a) == 2, что несколько удивительно, если вы не знаете о массивах, распадающихся на указатели.

0 голосов
/ 11 июля 2011

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

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