Разница между char [] и char * в вызове функции - PullRequest
1 голос
/ 20 февраля 2012

Я не смог объяснить, почему работает следующий фрагмент кода.Излишне говорить, что я новичок в C ++ ...

#include <cstdio>

void foo(char* p)
{
    p[0] = 'y';
}

int main()
{
    char a[1];
    a[0] = 'x';
    printf("a[0] = %c\n", a[0]);
    foo(a);
    printf("a[0] = %c\n", a[0]);
    return 0;
}

Эта программа выводит

a[0] = x
a[0] = y

Что нас заинтриговало, что я передаю не указатель, а массив,чтобы foo.Так как же foo может изменить значение массива a?Относится ли это только к массивам char?

Ответ на Разница между char и char [1] подтверждает мои наблюдения, но не дает подробных сведений о почему это тот случай.

Спасибо!

Ответы [ 7 ]

5 голосов
/ 20 февраля 2012

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

Следующее полностью эквивалентно:

void foo(char* p);
void foo(char p[]);
void foo(char p[42]); /* Or any other number. */ 

Применимо ли этотолько для массивов char?

Это относится к любому массиву.Я рекомендую aryptr раздел C FAQ .

4 голосов
/ 20 февраля 2012

В Си массивы в большинстве контекстов (*) распадаются на указатель на их первый элемент.

В вашем случае массив a распадается на указатель на a[0].

Массив int arr[12][23], когда используется только по его идентификатору, распадается на указатель на свой первый элемент, а именно arr[0], который имеет тип int (*)[23] (указатель на массив из 23-х дюймов).

(*) Массивы не затухают при использовании в качестве аргумента оператора sizeof, или при использовании в качестве аргумента оператора &, или при использовании в качестве инициализатора (строкового литерала) для массива символов.

1 голос
/ 20 февраля 2012

Вы можете попробовать это, чтобы убедить себя, как это работает.

int a[8], *p;
p = a;
printf("%p, %p, %p\n", a, &a[0], p);
1 голос
/ 20 февраля 2012

Когда вы говорите

char a[5];

компилятор выделяет 5 последовательных блоков памяти, а адрес первого блока назначается a. Таким образом, по определению имя массива (в нашем случае - это просто указатель на ячейку памяти).

Теперь, когда мы говорим [0], компилятор манипулирует им как * (a + 0 * sizeof (тип данных массива, т.е. char, int и т. Д.)), Символически a [i] представляется как * (a + i * sizeof (массив данных, например, char, int и т. д.))

Что касается передачи параметров функции Когда мы передаем массив в функцию, то в основном это просто адрес первого элемента, который передается. Для получения более подробной информации об этом PLZ перейдите по этой ссылке или прочитайте ответ @ cnicutar (поскольку он уже опубликовал правильный ответ, нет смысла повторять это снова) ...

0 голосов
/ 20 февраля 2012

Имя массива указывает на адрес первого элемента массива.Пожалуйста, обратитесь: Указывает ли имя массива?

0 голосов
/ 20 февраля 2012

Три прототипа здесь эквивалентны:

void foo(char *p);
void foo(char p[]);
void foo(char p[42]);

C говорит, что объявление параметра массива типа T скорректировано к объявлению указателя типа на T.

0 голосов
/ 20 февраля 2012

Массив - не более чем указатель (на первый элемент), по крайней мере, для передачи аргументов ради.

...