Прошу разъяснений по поводу «не передать по ссылке» в C - PullRequest
2 голосов
/ 08 марта 2019

После того, как попытался скомпилировать void some_function(int * & some_pointer); и получил ошибку компилятора: expected ';', ',' or ')' before '&' token. Я понял, что могу скомпилировать, только если для функции удалена ссылка на void some_function(int * some_pointer);

Исследуя, я нашел решение: «Нельзя пройти по ссылке в Си». Он не скомпилирует эту функцию.

Однако, это подняло бровь: scanf("%d", &my_var); Мы все время переходим по ссылке ... Как это работает? Я предполагаю, что мы не можем создавать функции, которые запрашивают ссылку, поскольку мы можем использовать ссылку в качестве аргументов. Программа передаст его по значению и впоследствии изменит исходную переменную. Это правильно?

Или функция запрашивает указатель, и когда мы используем &, она создает указатель на эту переменную? Я очень смущен.

Ответы [ 3 ]

2 голосов
/ 08 марта 2019

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

Например:

void f(int *x)
{
    *x = 4;
}

int main()
{
    int x = 0;
    printf("x=%d\n", x);    // prints 0
    f(&x);
    printf("x=%d\n", x);    // prints 4
}

Когда мы вызываем такую ​​функцию, как f(&x), *Оператор 1007 * берет адрес своего операнда и передает этот адрес в f.Это не ссылка.

1 голос
/ 08 марта 2019

Строго говоря, вы не можете передать по ссылке в C. Вместо этого, как в вашем примере scanf(), вы можете передать адрес переменной (он же указатель) по значению в функцию, и вы можете притвориться , что вы передали переменную по ссылке, но буквальная интерпретация вашего кода на C не согласилась бы с этим.

С другой стороны, вы можете использовать ссылки C ++, чтобы действительно передавать переменную по ссылке. Этот механизм, в отличие от вышеупомянутого, не использует преобразование областей памяти, т. Е. В данном случае C ++ (язык) ничего не знает об адресе переменной (хотя компилятор C ++ знает, ).

Итак, в C,

  • вы можете передать по ссылке (в «интерпретирующем» смысле).
  • ваш код C сам не может передать что-либо по ссылке.

С другой стороны, при использовании ссылок в C ++,

  • Вы можете передать по ссылке.
  • ваш код C ++ также может передаваться по ссылке.
1 голос
/ 08 марта 2019

Или функция, запрашивающая указатель, и когда мы ее используем, & создает указатель на эту переменную?

Это точно.

В C ++Символ & имеет несколько значений:

  • При применении в выражении в качестве унарного оператора это означает «получить адрес» и создает указатель;
  • Когда частьтип, подобный int& (или, на самом деле, int*&), это означает «ссылка на»;
  • (И, когда применяется как двоичный оператор между двумя арифметическими выражениями, это означает «побитовое значение »AND".)

С выбором использования & для ссылочных типов, я думаю, идея заключалась в том, чтобы сохранить создание новых символов и попытаться создать некоторую симметрию между указателями иРекомендации.Я не думаю, что это сработало;Я думаю, что это действительно сбивает с толку.

Но для вас, в C, это спорный вопрос, потому что (как вы обнаружили!) C не имеет ссылок.Вместо этого ваша функция может быть написана для получения указателя на указатель (int**).По иронии судьбы вам, вероятно, понадобится использовать & на сайте вызова, чтобы представить свой аргумент такой функции!

В качестве дополнительного усложнения вы иногда будете слышать фразу «передача по ссылке», используемую вширокий смысл.Это вводит в заблуждение в области C ++, потому что там «ссылка» имеет более конкретное значение.Фактически, ссылки были введены в язык C ++ специально для того, чтобы сделать «передачу по ссылке» более элегантной и интуитивно понятной.Но вернемся к Си и, в более общем смысле, это просто способ сказать: «мы ссылаемся на вещь, а не копируем ее»;технически в C способ, которым мы делаем это, действительно, чтобы передать указатель .

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