Проходя по ссылке в С - PullRequest
       26

Проходя по ссылке в С

190 голосов
/ 09 февраля 2010

Если C не поддерживает передачу переменной по ссылке, почему это работает?

#include <stdio.h>

void f(int *j) {
  (*j)++;
}

int main() {
  int i = 20;
  int *p = &i;
  f(p);
  printf("i = %d\n", i);

  return 0;
}

Вывод

$ gcc -std=c99 test.c
$ a.exe
i = 21 

Ответы [ 17 ]

4 голосов
/ 09 февраля 2010

Поскольку вы передаете указатель (адрес памяти) на переменную p в функцию f. Другими словами, вы передаете указатель, а не ссылку.

3 голосов
/ 09 февраля 2010

Вы не передаете int по ссылке, вы передаете указатель на int по значению. Другой синтаксис, одно и то же значение.

3 голосов
/ 09 февраля 2010

В C для передачи по ссылке вы используете оператор адреса &, который должен использоваться против переменной, но в вашем случае, поскольку вы использовали переменную-указатель p, вам не нужно ставить префикс это с адресом оператора. Это было бы верно, если бы вы использовали &i в качестве параметра: f(&i).

Вы также можете добавить это к разыменованию p и посмотреть, как это значение соответствует i:

printf("p=%d \n",*p);
2 голосов
/ 08 мая 2018

указатели и ссылки - это два разных слова.

Несколько вещей, которые я не видел, упоминались.

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

Ссылка должна рассматриваться как алиас чего-то. Он не имеет размера и не может быть сохранен. Это ДОЛЖНО ссылаться на что-то, т.е. он не может быть нулевым или измененным. Ну, иногда компилятору нужно хранить ссылку в виде указателя, но это деталь реализации.

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

1 голос
/ 09 февраля 2010

«Передача по ссылке» (с использованием указателей) была в C с самого начала. Почему вы думаете, что это не так?

1 голос
/ 21 ноября 2017

То, что вы делаете, это передача по значению, а не передача по ссылке. Потому что вы отправляете значение переменной 'p' в функцию 'f' (в основном как f (p);)

Та же программа на C с передачей по ссылке будет выглядеть так: (!!! эта программа выдает 2 ошибки, так как передача по ссылке не поддерживается в C)

#include <stdio.h>

void f(int &j) {    //j is reference variable to i same as int &j = i
  j++;
}

int main() {
  int i = 20;
  f(i);
  printf("i = %d\n", i);

  return 0;
}

Выход: -

3:12: error: expected ';', ',' or ')' before '&' token
             void f(int &j);
                        ^
9:3:  warning: implicit declaration of function 'f'
               f(a);
               ^
1 голос
/ 22 июня 2017

Я думаю, что C на самом деле поддерживает передачу по ссылке.

Большинство языков требуют, чтобы синтаксический сахар передавался по ссылке, а не по значению.(Например, C ++ требует & в объявлении параметра).

C также требует синтаксического сахара для этого.Это * в объявлении типа параметра и & в аргументе.Так что * и & - это синтаксис Си для передачи по ссылке.

Теперь можно утверждать, что для реального прохождения по ссылке требуется только синтаксис в объявлении параметра, а не на стороне аргумента.

Но теперь приходит C #, который поддерживает путем передачи ссылок и требует синтаксического сахара на как , так и сторонах аргумента и аргумента.

Аргумент, что C не имеет передачи by-ref, заставляет синтаксические элементы выражать его, демонстрируя основную техническую реализацию, вообще не является аргументом, поскольку это более или менее применимо ко всем реализациям.

Единственным оставшимся аргументом является то, что передача по ссылке в C не является монолитной функцией, но объединяет две существующие функции.(Возьмите ref аргумента от &, ожидайте, что ref напечатает *.) Например, C # требует двух синтаксических элементов, но их нельзя использовать друг без друга.

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

...