如果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语言不支持通过引用传递变量,为什么这样做呢?
#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语言毫无例外地采用值传递。传递指针 作为参数并不意味着引用传递。
规则如下:
函数不能改变实际的参数值。
(以上引自《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语言中。你为什么不这么认为?
因为在上面的代码中没有引用传递。使用指针(如void func(int* p))是通过地址传递的。 这是c++中的引用传递(在C中不起作用):
void func(int& ref) {ref = 4;}
...
int a;
func(a);
// a is 4 now
在C语言中,为了通过引用传递,你使用了地址操作符&,它应该用于一个变量,但在你的例子中,因为你已经使用了指针变量p,你不需要在它前面加上地址操作符。如果你使用&i作为参数:f(&i),这将是正确的。
你也可以添加这个,来解引用p,看看这个值如何匹配i:
printf("p=%d \n",*p);
你不是通过引用传递int型,而是通过值传递指向int型的指针。不同的语法,相同的意思。