C программирующий - передача ссылкой

В программе C ниже, я не понимаю, почему buf [0] = после того, как я назову нечто. Разве нечто не делает передачи значением?

#include <stdio.h>
#include <stdlib.h>

    void foo(char buf[])
    {
      buf[0] = 'A';
    }

    int main(int argc, char *argv[])
    {
      char buf[10];

      buf[0] = 'B';
      printf("before foo | buf[0] = %c\n", buf[0]);
      foo(buf);
      printf("after foo | buf[0] = %c\n", buf[0]);

      system("PAUSE"); 
      return 0;
      }

вывод:

before foo | buf[0] = 'B' 
after foo | buf[0] = 'A'
6
задан Kevin Meredith 5 August 2010 в 13:27
поделиться

12 ответов

void foo(char buf[])

то же самое, что и

void foo(char* buf)

Когда вы вызываете его, foo (buf) , вы передаете указатель по значению, поэтому создается копия указателя.

Копия указателя указывает на тот же объект, что и исходный указатель (или, в данном случае, на начальный элемент массива).

C не имеет семантики передачи по ссылке в том смысле, что C ++ имеет семантику передачи по ссылке. Все в C передается по значению. Указатели используются для получения семантики передачи по ссылке.

12
ответ дан 8 December 2019 в 04:50
поделиться

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

4
ответ дан 8 December 2019 в 04:50
поделиться

*char buf[] на самом деле означает char **, поэтому вы передаете по указателю/ссылке. Это дает вам понять, что buf является указателем, как в функции main(), так и в foo().

1
ответ дан 8 December 2019 в 04:50
поделиться

Потому что вы передаете указатель на buf (по значению). Поэтому содержимое, на которое указывает buf, изменяется.

1
ответ дан 8 December 2019 в 04:50
поделиться

Массив как параметр функции эквивалентен указателю, поэтому объявление

void foo( char buf[] );

такое же, как

void foo( char* buf );

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

2
ответ дан 8 December 2019 в 04:50
поделиться

Массивы обрабатываются иначе, чем другие типы; вы не можете передавать массив «по значению» в C.

Онлайн-стандарт C99 (черновик n1256) , раздел 6.3.2.1, «L-значения, массивы и указатели функций», параграф 3:

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

В вызове

foo(buf);

выражение массива buf не является операндом sizeof или & , и не является строковым литералом, используемым для инициализации массив, поэтому он неявно преобразуется («распадается») из типа «10-элементный массив char» в «указатель на char», а адрес первого элемента передается в foo. Следовательно, все, что вы делаете с buf в foo () , будет отражено в массиве buf в main () . Из-за того, как определяется индексирование массива, вы можете использовать оператор индекса для типа указателя, чтобы он выглядел так, как будто вы работаете с типом массива, но это не так.

В контексте объявления параметра функции, T a [] и T a [N] являются синонимами T * a , но это только случай, когда это правда.

2
ответ дан 8 December 2019 в 04:50
поделиться

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

Итак, значение указателя не меняется, но вы изменяете то, на что он указывает.

1
ответ дан 8 December 2019 в 04:50
поделиться

массивы и указатели (почти) одно и то же.

int* foo = malloc(...)

foo [2] то же самое, что * (foo + 2 * sizeof (int))

анекдот: вы написали

int main(int argc, char *argv[])

, это также допустимо (будет компилироваться и работать так же) написать

int main(int argc, char **argv)

, а также

int main(int argc, char argv[][])

они фактически одинаковы. это немного сложнее, потому что массив знает, сколько элементов у него есть, а указатель - нет. но они используются одинаково.

1
ответ дан 8 December 2019 в 04:50
поделиться

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

0
ответ дан 8 December 2019 в 04:50
поделиться

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

Если вы хотите сохранить содержимое исходного массива, вы можете скопировать строку во временное хранилище в функции.

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

0
ответ дан 8 December 2019 в 04:50
поделиться

обратите внимание на одну вещь,

объявление

void foo(char buf[])

говорит, что будет использоваться нотация []. Не то, какой элемент массива вы будете использовать.

Если вы хотите указать, что вы хотите получить какое-то конкретное значение, тогда вы должны объявить эту функцию как

void foo(char buf[X]); //where X would be a constant.

Конечно, это невозможно, потому что это было бы бесполезно (функция для работы с n-м элементом массива?). Вам не нужно записывать информацию, какой элемент массива вы хотите получить. Все, что вам нужно, это простое объявление:

voi foo(char value);

so ...

void foo(char buf[])

- это объявление, в котором указано, какую нотацию вы хотите использовать ([] - часть), а также оно содержит указатель на некоторые данные.

Более того ... чего вы ожидаете ... вы отправили функции foo имя массива

foo(buf);

, которое эквивалентно & buf [0]. Итак ... это указатель.

0
ответ дан 8 December 2019 в 04:50
поделиться

Массивы в C не передаются по значению. Они даже не являются допустимыми параметрами функции. Вместо этого компилятор видит, что вы пытаетесь передать массив, и понижает его статус до указателя. Он делает это тихо, потому что это зло. Еще он любит пинать щенков.

Использование массивов в параметрах функции - хороший способ сообщить вашим пользователям API, что эта штука должна быть блоком памяти, сегментированным на блоки размером n байтов, но не ожидайте, что компиляторы позаботятся, если вы напишете char * foo char foo [] или char foo [12] в параметрах функции. Они этого не сделают.

0
ответ дан 8 December 2019 в 04:50
поделиться
Другие вопросы по тегам:

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