Это вызов по ссылке или по значению? С - PullRequest
0 голосов
/ 27 июня 2018

Я читаю книгу под названием язык программирования c, написанную Брайаном В. Керниганом и Деннисом М. Ричи.

В книге указан код ниже:

void strcpy(char *s, char *t){
    while((*s = *t) != '\0'){
        s++;
        t++;
    }
}

и говорит:

Поскольку аргументы передаются по значению, strcpy может использовать параметры с и т любым удобным способом

, с которым я не согласен. Почему аргументы передаются по значению?

Согласно другой книге C, как программировать:

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

В последнем случае, это определенно вызов по ссылке.

Скажите, пожалуйста, какой путь правильный и почему, спасибо!

Кстати, после присвоения * s = * t, какое из них сравнивается с '\ 0'? * s или * t?

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Многие люди считают, что эта идиома не является ни вызовом по значению, ни вызовом по ссылке. Что бы это ни стоило, Кернигана и Ритчи * Язык программирования C вызывает массивы и указатели в «ссылках» на C, хотя в нем используется только термин «вызов по значению», а не вызов по ссылке. Такое использование, похоже, вышло из моды после того, как C ++ добавил другую языковую функцию, называемую ссылками.

Функция, которая принимает указатель и разыменовывает, как правило, компилируется в тот же машинный код, что и функция в языке с вызовом по ссылке. Единственное отличие, которое заключается не только в отсутствии синтаксического сахара: если сам аргумент-указатель не const, можно переназначить ему новое значение и сделать так, чтобы оно ссылалось на что-то другое, что делает семантика «вызов по ссылке» не разрешено. В языке с вызовом по ссылке вы не можете написать s++ или t++, чтобы аргументы функции ссылались на разные объекты! (Строки C хранятся таким образом, что вы можете добавить смещение к указателю, чтобы получить подстроку, тогда как большинство языков хранит длину строки в первых нескольких байтах ее памяти.) Однако вы можете думать о ссылка T& в C ++ эквивалентна передаче T *const, которая гарантированно не будет NULL, и перед ее именем стоит невидимая звездочка.

0 голосов
/ 27 июня 2018

C всегда передает аргументы по значению, что означает, что вызываемая функция получает локальную копию того, на что ссылается вызывающая сторона.

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

char *test(char *s) {
  s++;
  return s;
}

t = test("A");

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

Но strcpy () вашего примера делает что-то другое: он принимает указатель s, а изменяет то, что указывает на . Указатели являются мощными, и их можно использовать для имитации «передачи по ссылке» (указатель является ссылкой).

после присвоения * s = * t, какое из них сравнивается с '\ 0'? * s или * t?

* s: в C присваивание возвращает значение - а значением является значение присвоенной переменной после выполнения присваивания. Запись:

if (i=3) ...

совпадает с

i=3;
if (i) ...

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

...