如果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语言中,一切都是值传递。指针的使用给我们一种通过引用传递的错觉,因为变量的值发生了变化。但是,如果您要打印指针变量的地址,您将看到它不会受到影响。地址值的副本被传递给函数。下面是一个演示片段。

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

其他回答

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

您正在按值传递一个指针(地址位置)。

这就像是在说“这里有我想让你更新的数据”。

在C语言中,模拟了引用传递 通过传递变量的地址 (一个指针)并对其进行解引用 地址内的函数读取或 写出实际的变量。这将 被称为“C风格” 引用传递”。

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

在C语言中,为了通过引用传递,你使用了地址操作符&,它应该用于一个变量,但在你的例子中,因为你已经使用了指针变量p,你不需要在它前面加上地址操作符。如果你使用&i作为参数:f(&i),这将是正确的。

你也可以添加这个,来解引用p,看看这个值如何匹配i:

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

将指针称为引用(如Java和Javascript所做的)与引用传递(pass-by-reference)是完全不同的用法。C不支持引用传递。下面是重新编写的示例,以显示它不是真正地通过引用传递值,而是通过值传递指针。

#include <stdio.h>

void f(int *j) {
  int k = (*j) + 1;
  j = &k;
}

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


  printf("i(ptr) = %p\n", &i);
  printf("j(ptr) = %p\n", p);


  return 0;
}

这是输出

i = 20
j = 20
i(ptr) = 0x7ffdfddeee1c
j(ptr) = 0x7ffdfddeee1c

如您所见,值保持不变,但更重要的是指针也没有改变。然而,c++允许通过引用传递。下面是通过c++编译器实现的相同示例,但在头文件中添加了&号,使其成为引用参数。

#include <stdio.h>

void f(int *&j) {   // note the & makes this a reference parameter.
                    // can't be done in C
  int k = (*j) + 1;
  j = &k;
}

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


  printf("i(ptr) = %p\n", &i);
  printf("j(ptr) = %p\n", p);


  return 0;
}

这是输出

i = 20
j = 21
i(ptr) = 0x7ffcb8fc13fc
j(ptr) = 0x7ffcb8fc13d4

注意,我们可以改变实际的指针!

作为参考,The Dragon Book是一本关于编译器的经典计算机科学教科书。因为它是有史以来最受欢迎的编译器书籍(至少在我上大学的时候是这样,也许我错了),我猜绝大多数设计语言或编写编译器的人都是从这本书中学习的。本书的第一章非常清楚地解释了这些概念,并解释了为什么C语言只采用值传递。