C语言 在 C 中通过引用传递

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2229498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:26:22  来源:igfitidea点击:

Passing by reference in C

cpointerspass-by-reference

提问by aks

If C does not support passing a variable by reference, why does this work?

如果 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;
}

Output:

输出:

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

回答by tvanfosson

Because you're passing the valueof the pointer to the method and then dereferencing it to get the integer that is pointed to.

因为您将指针的值传递给该方法,然后取消引用它以获取指向的整数。

回答by Ely

That is not pass-by-reference, that is pass-by-value as others stated.

这不是按引用传递,而是正如其他人所说的按值传递。

The C language is pass-by-value without exception. Passing a pointer as a parameter does not mean pass-by-reference.

C语言无一例外都是按值传递的。将指针作为参数传递并不意味着通过引用传递。

The rule is the following:

规则如下:

A function is not able to change the actual parameters value.

函数无法更改实际参数值。



Let's try to see the differences between scalar and pointer parameters of a function.

让我们试着看看函数的标量参数和指针参数之间的区别。

Scalar variables

标量变量

This short program shows pass-by-value using a scalar variable. paramis called the formal parameter and variableat function invocation is called actual parameter. Note incrementing paramin the function does not change variable.

这个简短的程序使用标量变量显示按值传递。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;
}

The result is

结果是

I've received value 111
variable=111

Illusion of pass-by-reference

传递引用的错觉

We change the piece of code slightly. paramis a pointer now.

我们稍微更改了这段代码。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;
}

The result is

结果是

I've received value 111
variable=112

That makes you believe that the parameter was passed by reference. It was not. It was passed by value, the param value being an address. The int type value was incremented, and that is the side effect that make us think that it was a pass-by-reference function call.

这让您相信该参数是通过引用传递的。不是。它是按值传递的,参数值是一个地址。int 类型的值增加了,这就是副作用,让我们认为它是一个传递引用函数调用。

Pointers - passed-by-value

指针 - 按值传递

How can we show/prove that fact? Well, maybe we can try the first example of Scalar variables, but instead of scalar we use addresses (pointers). Let's see if that can help.

我们如何展示/证明这一事实?好吧,也许我们可以尝试标量变量的第一个示例,但是我们使用地址(指针)代替标量。让我们看看这是否有帮助。

#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 ptrwould be NULLafter function invocation.

在我看来,这清楚地证明了指针是按值传递的。否则ptrNULL在函数调用之后。

回答by Ely

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."

在 C 中,通过传递变量(指针)的地址并在函数内取消引用该地址以读取或写入实际变量来模拟传递引用。这将被称为“C 风格传递引用”。

Source: www-cs-students.stanford.edu

资料来源:www-cs-students.stanford.edu

回答by Alexander Gessler

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* p))是按地址传递的。这是 C++ 中的传递引用(在 C 中不起作用):

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

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

回答by Daniel Vassallo

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.

虽然 C 不支持引用数据类型,但您仍然可以通过显式传递指针值来模拟按引用传递,如您的示例所示。

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:

C++ 引用数据类型不那么强大,但被认为比从 C 继承的指针类型更安全。这将是您的示例,适用于使用C++ 引用

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

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

  return 0;
}

回答by antony.trupe

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

您正在通过value传递一个指针(地址位置)。

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

这就像说“这是我希望您更新数据的地方。”

回答by Anssi

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

p 是一个指针变量。它的值是 i 的地址。当你调用 f 时,你传递了p的值,也就是 i 的地址。

回答by Pavel Radzivilovsky

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

在 C 中没有传递引用,但是 p “引用”到 i,并且您通过值传递 p。

回答by Arun Suresh

In C everything is pass-by-value. The use of pointers gives us the illusion that we are passing by reference because the valueof 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 copyof the valueof the address is passed-in to the function. Below is a snippet illustrating that.

在 C 中,一切都是按值传递的。指针的使用给我们一种错觉,认为我们是通过引用传递的,因为变量的发生了变化。但是,如果您要打印出指针变量的地址,您将看到它不会受到影响。一个副本的的价值地址被传入到函数。下面是一个片段,说明了这一点。

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

回答by Francisco Zapata

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

简短回答:是的,C 确实使用指针实现了按引用传递的参数。

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-Value(输入模式语义) Pass-by-Result(输出模式语义) Pass-by-Value-Result(输入模式语义) Pass-by-Reference(输入模式语义) Pass-by-Name(输入模式语义)语义)

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.

通过引用传递是用于 inout 模式参数传递的第二种技术。运行时系统不是在主程序和子程序之间来回复制数据,而是发送一个直接访问子程序数据的路径。在这个策略中,子程序可以直接访问数据,有效地与主程序共享数据。这种技术的主要优点是它在时间和空间上绝对高效,因为不需要复制空间,也没有数据复制操作。

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.

C 中的参数传递实现:C 使用指针作为参数实现按值传递和按引用传递(inout 模式)语义。指针被发送到子程序,根本不复制实际数据。但是,由于指针是访问主程序数据的路径,子程序可能会更改主程序中的数据。C 从 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.

C++ 中的参数传递实现:C++ 还使用指针和一种称为引用类型的特殊指针来实现按引用传递(inout 模式)语义。引用类型指针在子程序内部被隐式取消引用,但它们的语义也是通过引用传递的。

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.

有关更多信息,请参阅 Robert Sebesta 所著的《编程语言概念》一书,第 10 版,第 9 章。