Проблема с передачей указателей в качестве аргумента в пользовательскую функцию в C ++ - PullRequest
0 голосов
/ 16 мая 2019

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

Я ожидал:

Second&First
Second*First

Но вывод:

Second&First
First*Second

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

void Alter(char* X, char* Y){
char* T;
cout<<"&S1="<<&X<<"&S2="<<&Y<<endl;
T=X;
X=Y;
Y=T;
cout<<X<<"&"<<Y<<endl;}

void main(){
char X[]="First", Y[]="Second";
cout<<"&x="<<&X<<"&y="<<&Y<<endl;
Alter(X,Y);
cout<<"&x="<<&X<<"&y="<<&Y<<endl;
cout<<X<<"*"<<Y;getch();}

Ответы [ 3 ]

2 голосов
/ 16 мая 2019

Вывод правильный.Ваши ожидания несколько отличаются от фактического поведения.

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

Смотрите шаг за шагом, что происходит.

1) char X[]="First", Y[]="Second";

----------------
|      F       | <--- X
----------------

...

----------------
|      S       | <--- Y
----------------

2) cout<<"&x="<<&X<<"&y="<<&Y<<endl;

Адреса указателей X и Y выводятся на экран.

3) Alter(X,Y);

При выполнении этого вызова функции указатели X и Y копируются в параметры функции Alter, скажем, X 'и Y'

----------------
|      F       | <--- X, X'
----------------

...

----------------
|      S       | <--- Y, Y'
----------------

4) T=X; X=Y; Y=T;

При выполнении этого кода меняются местами указатели X и Y.

----------------
|      F       | <--- X, Y'
----------------

...

----------------
|      S       | <--- Y, X'
----------------

5) cout<<X<<"&"<<Y<<endl;

Как вы можетесм. на шаге 4, поскольку X указывает на область памяти, содержащую «S», «Second» печатается первым, а «First» печатается позже.

6) cout<<"&x="<<&X<<"&y="<<&Y<<endl;

Перед выполнениемэтой инструкции параметры функции Alter вышли из области видимости.

Итак, теперь сценарий такой:

----------------
|      F       | <--- X
----------------

...

----------------
|      S       | <--- Y
----------------

7) cout<<X<<"*"<<Y;

Как вы видите на шаге 6, поскольку X указывает на ячейку памяти, содержащую «F», «First» печатается первым, а «Second» печатается позже.

2 голосов
/ 16 мая 2019

Да, ваша концепция полностью неверна.

В вашей Alter() функции, которую я здесь упрощаю (для удаления посторонних выводов, не связанных с вашим вопросом)

void Alter(char* X, char* Y)
{
    char* T;
    T = X;
    X = Y;
    Y = T;
    cout<<X<<"&"<<Y<<endl;
}

X и Y являются указателями и передаются по значению. Таким образом, назначения X = Y и Y = T не видны вызывающей стороне, то есть main(). В частности, назначения в функции (X = Y и Y = T) не имеют эффекта, видимого для main().

Однако X и Y каждая указывает (или может использоваться для ссылки) на что-то - в вашем коде первый символ массивов в main(). Эти функции в функции: *X и *Y. Одно архаичное описание, которое, похоже, используется в вашей учебной книге, - это то, что они «передаются по ссылке».

Если мы изменим Alter(), чтобы назначить *X и *Y, а именно

void Alter(char* X, char* Y)
{
    char T;         //  note the missing * here relative to your code
    T = *X;         //  note the added * in this line
    *X = *Y;        // note the added *s in this line and the next
    *Y = *T;
    cout<<X<<"&"<<Y<<endl;    // this statement is unchanged
}

В этом случае вывод будет

Sirst&Fecond
Sirst&Fecond

(т. Е. Первые символы массивов меняются местами, и этот эффект виден для main()).

Мы также можем изменить Alter() на

void Alter(char*& X, char*& Y)      //  note the ampersands here
{
    char* T;
    T = X;
    X = Y;
    Y = T;
    cout<<X<<"&"<<Y<<endl;
}

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

Однако, ваш пример main() (который опять-таки просто удалить лишний вывод) не скомпилируется с использованием этой функции

int main()         //  main() returns int in standard C++, not void
{
    char X[]="First", Y[]="Second";

    Alter(X,Y);
    cout<<X<<"*"<<Y;
}

Это не скомпилируется, потому что X и Y в main() являются массивами, а массивы НЕ являются указателями - поэтому они не могут быть переданы функции, которая ожидает передачи ссылок на указатели. Это означает, что ваша функция Alter() не может использоваться для замены массивов в main().

1 голос
/ 16 мая 2019

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

Таким образом, сами указатели передаются по значению.Говорят, что содержимое , на которое они указывают , передается по ссылке.

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

В вашем примере X и Y - указатели;они содержат начальные адреса «Первый» и «Второй».«Первый» и «Второй» - это данные, на которые указывают X и Y соответственно.

Рассмотрим операторы, полученные из вашей программы, используя только printf вместо cout:

char X[] = "First";

// Prints "First"
printf("%s", X);

// Prints address of 'F' in memory
printf("%x", X);

// Prints address of X - the location where the value printed above is stored
printf("%x", &X);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...