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

当前回答

因为你传递了一个指向变量p的指针(内存地址)到函数f中。换句话说,你传递的是一个指针而不是一个引用。

其他回答

因为在上面的代码中没有引用传递。使用指针(如void func(int* p))是通过地址传递的。 这是c++中的引用传递(在C中不起作用):

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

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

“通过引用传递”(通过使用指针)从一开始就存在于C语言中。你为什么不这么认为?

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

C语言毫无例外地采用值传递。传递指针 作为参数并不意味着引用传递。

规则如下:

函数不能改变实际的参数值。

(以上引自《K&R》一书)


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

标量变量

这个简短的程序展示了使用标量变量的值传递。参数被称为形式参数,函数调用时的变量被称为实际参数。注意在函数中增加参数并不会改变变量。

#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

这使您相信参数是通过引用传递的。但事实并非如此。它通过值传递,参数值是一个地址。int类型的值增加了,这是副作用,使我们认为这是一个引用传递函数调用。

指针——按值传递

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

#include <stdio.h>

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

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

    function2(ptr);
    printf("address ptr is pointing to %d\n", ptr);
    return 0;
}

结果将是两个地址相等(不要担心确切的值)。

结果示例:

address param is pointing to -1846583468
address ptr   is pointing to -1846583468

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

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

在实现参数传递时,编程语言的设计者使用三种不同的策略(或语义模型):将数据传输到子程序,从子程序接收数据,或者两者都做。这些模型通常分别称为in模式、out模式和inout模式。

语言设计者设计了几个模型来实现这三个基本参数传递策略:

值传递(在模式语义中) 结果传递(out模式语义) 值-结果传递(inout模式语义) 引用传递(inout模式语义) 名称传递(inout模式语义)

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.

C中的参数传递实现: C使用指针作为参数实现了值传递和引用传递(inout模式)语义。指针被发送到子程序,根本不复制实际数据。然而,由于指针是主例程数据的访问路径,子程序可以改变主例程中的数据。C采用了ALGOL68的方法。

c++中的参数传递实现: c++还使用指针实现了引用传递(inout模式)语义,也使用了一种特殊类型的指针,称为引用类型。引用类型指针在子程序内部隐式地解引用,但它们的语义也是引用传递的。

这里的关键概念是引用传递实现了数据的访问路径,而不是将数据复制到子程序中。数据访问路径可以是显式解引用指针或自动解引用指针(引用类型)。

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

你不是通过引用传递int型,而是通过值传递指向int型的指针。不同的语法,相同的意思。