Какой смысл несет слово «имитация» в словосочетании «имитация передачи аргументов по ссылке»?
Давно хотел спросить, для чего здесь слово "симуляция"?
In C, you use pointers and the indirection operator to simulate pass-by-reference. When calling a function with arguments that should be modified, the addresses of the arguments are passed.
В языке C указатели и оператор косвенного доступа используются для имитации передачи аргументов по ссылке. Когда функция должна изменить значение аргумента, ей передается адрес этого аргумента.
5.9 Passing Arguments By Value and By Reference
In many programming languages, there are two ways to pass arguments—pass-by-value and pass-by-reference. When arguments are passed by value, a copy of the argument’s value is made and passed to the called function. Changes to the copy do not affect an original variable’s value in the caller. When an argument is passed by reference, the caller allows the called function to modify the original variable’s value.
Pass-by-value should be used whenever the called function does not need to modify the value of the caller’s original variable. This prevents the accidental side effects (variable modifications) that so greatly hinder the development of correct and reliable software systems. Pass-by-reference should be used only with trusted called functions that need to modify the original variable.
In C, all arguments are passed by value. As we’ll see in Chapter 7, it’s possible to simulate pass-by-reference by using the address operator and the indirection operator. In Chapter 6, we’ll see that array arguments are automatically passed by reference for performance reasons. We’ll see in Chapter 7 that this is not a contradiction. For now, we concentrate on pass-by-value.
6.5 Passing Arrays to Functions
Recall that all arguments in C are passed by value. C automatically passes arrays to functions by reference (again, we’ll see in Chapter 7 that this is not a contradiction)—the called functions can modify the element values in the callers’ original arrays. The name of the array evaluates to the address of the first element of the array. Because the starting address of the array is passed, the called function knows precisely where the array is stored. Therefore, when the called function modifies array elements in its function body, it’s odifying the actual elements of the array in their original memory locations. Причем, в параметрах функции будет объявлен указатель (либо массив, который будет преобразован в указатель) и под него будет зарезервирована память.
7.1 Introduction
In this chapter, we discuss one of the most powerful features of the C programming language, the pointer. Pointers are among C’s most difficult capabilities to master. Pointers enable programs to simulate pass-by-reference, to pass functions between functions, and to create and manipulate dynamic data structures, i.e., data structures that can grow and shrink at execution time, such as linked lists, queues, stacks and trees. This chapter explains basic pointer concepts. Chapter 10 examines the use of pointers with structures. Chapter 12 introduces dynamic memory management techniques and presents examples of creating and using dynamic data structures.
7.2 Pointer Variable Definitions and Initialization
Pointers are variables whose values are memory addresses. Normally, a variable directly contains a specific value. A pointer, on the other hand, contains an address of a variable that contains a specific value. In this sense, a variable name directly references a value, and a pointer indirectly references a value (Fig. 7.1). Referencing a value through a pointer is called indirection.
7.4 Passing Arguments to Functions by Reference
There are two ways to pass arguments to a function—pass-by-value and pass-by-reference. All arguments in C are passed by value. As we saw in Chapter 5, return may be used to return one value from a called function to a caller (or to return control from a called function without passing back a value). Many functions require the capability to modify variables in the caller or to pass a pointer to a large data object to avoid the overhead of passing the object by value (which incurs the time and memory overheads of making a copy of the object).
In C, you use pointers and the indirection operator to simulate pass-by-reference. When calling a function with arguments that should be modified, the addresses of the arguments are passed. This is normally accomplished by applying the address operator (&) to the variable (in the caller) whose value will be modified. As we saw in Chapter 6, arrays are not passed using operator & because C automatically passes the starting location in memory of the array (the name of an array is equivalent to &arrayName[0]). When the address of a variable is passed to a function, the indirection operator (*) may be used in the function to modify the value at that location in the caller’s memory.
Три: Получается, на этапе изучения С не очень правильно говорить "передача по ссылке", при том что нет ничего трудного в 10 строчках кода, демонстрирующих адреса указателей, объявленных в main и в какой-нибудь функции. Потому что читается так, будто при by value есть "копирование", а при взятии адреса и передаче его в указатель из параметров функции - нет. Хотя достаточно взглянуть например на .obj код и смысл станет понятен. Не нужно было зацикливаться на этих словах "имитация", без демонстрации ссылок из С++ это бессмысленно))) Зачем нужно было писать pass-by-reference вообще непонятно... Это действительно симуляция-имитация.
#include <stdio.h>
void byValue ( int a );
void byPointer ( int * b );
void byValueAgain ( int c );
//void byRef( int &d );// в С нет.
int main( void ) {
int x = 3;// будет зарезервирована память размером int под значение 3 под именем x.
int * xPtr;
printf ("%p\n", &x);//0028FF3C
printf ("%p\n", &xPtr);//0028FF38
byValue ( x );//0028FF20
byPointer ( &x );//0028FF20
byValueAgain ( x );//0028FF20
//beRef( x );// в С нет. Но было бы тоже 0028FF20
}
//Написать параметр функции тоже самое, что определить переменную в main.
void byValue ( int a ){ // будет зарезервирована память размером int под значение x под именем a (тип данных int). Произойдет копирование x.
printf ("%p\n", &a);
a = a * 2;
}
void byPointer ( int * b ){// будет зарезервирована память размером длины адреса в системе под значение адреса x под именем b (тип данных int *). Произойдет копирование адреса x.
printf ("%p\n", &b );
*b = *b * 2;// с помощью оператора * будет выполнен доступ по адресу к x и его непосредственное изменению.
}
void byValueAgain ( int c ){
printf ("%p\n", &c );
}
//void byRef ( int &d ){// будет зарезервирована память размером длины адреса в системе под значение адреса x под именем d (тип данных int &).
// printf ("%p\n", &d);
// d = d * 2;
//}
То есть ссылка - это просто эволюция указателя по направлению высокоуровневости языка. Она решает те же задачи, что и указатель, только без нужды запариваться с операторами adress operator и dereferencing operator. Не нужно разыменовывать ссылку, она и так работает как будто обычная переменная. Но и арифметика указателей с сылкой работать, понятно, уже не будет.
В Си нету такого понятия как "ссылка" (это понятие из С++) и Си-шный код может только имитировать такое поведение как "передача по ссылке", используя указатели.
C всегда передает аргументы по значению. Для имитации передачи по ссылке передается значение указателя. Всегда по ссылке передают аргументы Fortran и Perl. В C++ можно передавать и по ссылке и по значению.
Ссылка - это псевдоним, второе имя переменной.
Указатель - это адрес в памяти где хранится значение.
Ссылка - абстракция выше чем указатель на память. Ссылка не знает об организации памяти - это просто псевдоним. Указатель - только один из способов реализации ссылки.
При передаче по значению делается копия переменной (в C для имитации call-by-reference копируется указатель).
При передаче по ссылке - передается псевдоним переменной.
В Си нету такого понятия как "ссылка" (это понятие из С++).
В С++ ссылки используют для изменения переменных на которые ссылается ссылка.
В Си для этого используют указатель.
Что бы еще больше имитировать ссылку, можно аргумент функции объявлять как константный указатель: void func(char * const str);