IT story

C에서 참조로 전달

hot-time 2020. 5. 10. 10:27
반응형

C에서 참조로 전달


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 

포인터 의 값 을 메소드에 전달한 다음 참조하는 정수를 얻기 위해 역 참조하기 때문입니다.


그것은 참조에 의한 전달이 아니며 다른 사람들이 언급 한 것처럼 값에 의한 전달입니다.

C 언어는 예외없이 가치를 전달합니다. 포인터를 매개 변수로 전달한다고해서 참조로 전달되는 것은 아닙니다.

규칙은 다음과 같습니다.

함수가 실제 매개 변수 값을 변경할 수 없습니다.


함수의 스칼라 매개 변수와 포인터 매개 변수의 차이점을 살펴 보겠습니다.

스칼라 변수

이 짧은 프로그램은 스칼라 변수를 사용하여 값별 패스를 보여줍니다. param공식 매개 변수라고 variable하며 함수 호출시 실제 매개 변수라고합니다. param기능의 증가 는 변하지 않습니다 variable.

#include <stdio.h>

void function(int param) {
    printf("I've received value %d\n", param);
    param++;
}

int main(void) {
    int variable = 111;

    function(variable);
    printf("variable %d\m", variable);
    return 0;
}

결과는

I've received value 111
variable=111

통과 기준의 환영

코드 조각을 약간 변경합니다. param포인터입니다.

#include <stdio.h>

void function2(int *param) {
    printf("I've received value %d\n", *param);
    (*param)++;
}

int main(void) {
    int variable = 111;

    function2(&variable);
    printf("variable %d\n", variable);
    return 0;
}

결과는

I've received value 111
variable=112

그러면 매개 변수가 참조로 전달되었다고 믿을 수 있습니다. 아니었다. 값으로 전달되었으며 param 값은 주소입니다. int 타입 값이 증가했고, 그것이 참조에 의한 함수 호출이라고 생각하게 만드는 부작용입니다.

포인터-값으로 전달

그 사실을 어떻게 증명 / 증명할 수 있습니까? 스칼라 변수의 첫 번째 예제를 시도해 볼 수 있지만 스칼라 대신 주소 (포인터)를 사용합니다. 그것이 도움이 될 수 있는지 봅시다.

#include <stdio.h>

void function2(int *param) {
    printf("param's address %d\n", param);
    param = NULL;
}

int main(void) {
    int variable = 111;
    int *ptr = &variable;

    function2(ptr);
    printf("ptr's address %d\n", ptr);
    return 0;
}

The result will be that the two addresses are equal (don't worry about the exact value).

Example result:

param's address -1846583468
ptr's address -1846583468

In my opinion this proves clearly that pointers are passed-by-value. Otherwise ptr would be NULL after function invocation.


In C, Pass-by-reference is simulated by passing the address of a variable (a pointer) and dereferencing that address within the function to read or write the actual variable. This will be referred to as "C style pass-by-reference."

Source: www-cs-students.stanford.edu


Because there is no pass-by-reference in the above code. Using pointers (such as void func(int* p)) is pass-by-address. This is pass-by-reference in C++ (won't work in C):

void func(int& ref) {ref = 4;}

...
int a;
func(a);
// a is 4 now

Your example works because you are passing the address of your variable to a function that manipulates its value with the dereference operator.

While C does not support reference data types, you can still simulate passing-by-reference by explicitly passing pointer values, as in your example.

The C++ reference data type is less powerful but considered safer than the pointer type inherited from C. This would be your example, adapted to use C++ references:

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

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

  return 0;
}

You're passing a pointer(address location) by value.

It's like saying "here's the place with the data I want you to update."


p is a pointer variable. Its value is the address of i. When you call f, you pass the value of p, which is the address of i.


No pass-by-reference in C, but p "refers" to i, and you pass p by value.


In C everything is pass-by-value. The use of pointers gives us the illusion that we are passing by reference because the value of the variable changes. However, if you were to print out the address of the pointer variable, you will see that it doesn't get affected. A copy of the value of the address is passed-in to the function. Below is a snippet illustrating that.

void add_number(int *a) {
    *a = *a + 2;
}

int main(int argc, char *argv[]) {
   int a = 2;

   printf("before pass by reference, a == %i\n", a);
   add_number(&a);
   printf("after  pass by reference, a == %i\n", a);

   printf("before pass by reference, a == %p\n", &a);
   add_number(&a);
   printf("after  pass by reference, a == %p\n", &a);

}

before pass by reference, a == 2
after  pass by reference, a == 4
before pass by reference, a == 0x7fff5cf417ec
after  pass by reference, a == 0x7fff5cf417ec

Because you're passing a pointer(memory address) to the variable p into the function f. In other words you are passing a pointer not a reference.


Short answer: Yes, C does implement parameter passing by reference using pointers.

While implementing parameter passing, designers of programming languages use three different strategies (or semantic models): transfer data to the subprogram, receive data from the subprogram, or do both. These models are commonly known as in mode, out mode, and inout mode, correspondingly.

Several models have been devised by language designers to implement these three elementary parameter passing strategies:

Pass-by-Value (in mode semantics) Pass-by-Result (out mode semantics) Pass-by-Value-Result (inout mode semantics) Pass-by-Reference (inout mode semantics) Pass-by-Name (inout mode semantics)

Pass-by-reference is the second technique for inout-mode parameter passing. Instead of copying data back and forth between the main routine and the subprogram, the runtime system sends a direct access path to the data for the subprogram. In this strategy the subprogram has direct access to the data effectively sharing the data with the main routine. The main advantage with this technique is that its absolutely efficient in time and space because there is no need to duplicate space and there is no data copying operations.

Parameter passing implementation in C: C implements pass-by-value and also pass-by-reference (inout mode) semantics using pointers as parameters. The pointer is send to the subprogram and no actual data is copied at all. However, because a pointer is an access path to the data of the main routine, the subprogram may change the data in the main routine. C adopted this method from ALGOL68.

Parameter passing implementation in C++: C++ also implements pass-by-reference (inout mode) semantics using pointers and also using a special kind of pointer, called reference type. Reference type pointers are implicitly dereferenced inside the subprogram but their semantics are also pass-by-reference.

So the key concept here is that pass-by-reference implements an access path to the data instead of copying the data into the subprogram. Data access paths can be explicitly dereferenced pointers or auto dereferenced pointers (reference type).

For more info please refer to the book Concepts of Programming Languages by Robert Sebesta, 10th Ed., Chapter 9.


You're not passing an int by reference, you're passing a pointer-to-an-int by value. Different syntax, same meaning.


In C, to pass by reference you use the address-of operator & which should be used against a variable, but in your case, since you have used the pointer variable p, you do not need to prefix it with the address-of operator. It would have been true if you used &i as the parameter: f(&i).

You can also add this, to dereference p and see how that value matches i:

printf("p=%d \n",*p);

pointers and references are two different thigngs.

A couple of things I have not seen mentioned.

A pointer is the address of something. A pointer can be stored and copied like any other variable. It thus have a size.

A reference should be seen as an ALIAS of something. It does not have a size and cannot be stored. It MUST reference something, ie. it cannot be null or changed. Well, sometimes the compiler needs to store the reference as a pointer, but that is an implementation detail.

With references you don't have the issues with pointers, like ownership handling, null checking, de-referencing on use.


'Pass by reference' (by using pointers) has been in C from the beginning. Why do you think it's not?


I think C in fact supports pass by reference.

Most languages require syntactic sugar to pass by reference instead of value. (C++ for example requires & in the parameter declaration).

C also requires syntactic sugar for this. It's * in the parameter type declaration and & on the argument. So * and & is the C syntax for pass by reference.

One could now argue that real pass by reference should only require syntax on the parameter declaration, not on the argument side.

But now comes C# which does support by reference passing and requires syntactic sugar on both parameter and argument sides.

The argument that C has no by-ref passing cause the the syntactic elements to express it exhibit the underlying technical implementation is not an argument at all, as this applies more or less to all implementations.

The only remaining argument is that passing by ref in C is not a monolithic feature but combines two existing features. (Take ref of argument by &, expect ref to type by *.) C# for example does require two syntactic elements, but they can't be used without each other.

This is obviously a dangerous argument, cause lots of other features in languages are composed of other features. (like string support in C++)


What you are doing is pass by value not pass by reference. Because you are sending the value of a variable 'p' to the function 'f' (in main as f(p);)

The same program in C with pass by reference will look like,(!!!this program gives 2 errors as pass by reference is not supported in 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;
}

Output:-

3:12: error: expected ';', ',' or ')' before '&' token
             void f(int &j);
                        ^
9:3:  warning: implicit declaration of function 'f'
               f(a);
               ^

참고URL : https://stackoverflow.com/questions/2229498/passing-by-reference-in-c

반응형