如果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
func
: func(&A);
这将在不复制任何内容的情况下将指向A的指针传递给函数。虽然这是按值传递,但该值是一个引用,因此您正在“按引用传递”变量A。不需要复制任何内容。可以说这是按引用传递。 - ICW正如其他人所说,这不是按引用传递,而是按值传递。
C语言在任何情况下都是按值传递。将指针作为参数传递并不意味着按引用传递。
规则如下:
函数无法更改实际参数的值。
(上面的引文实际上来自K&R的书)
让我们尝试了解函数的标量和指针参数之间的区别。
此短程序使用标量变量显示按值传递。 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
这让你相信参数是按引用传递的。但实际上不是这样,它是按值传递的,参数的值是一个地址。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
。
以上代码中没有传递引用。使用指针(例如void func(int* p)
)是通过地址传递。
这是C++中的传递引用的方法(在C中无效):
void func(int& ref) {ref = 4;}
...
int a;
func(a);
// a is 4 now
C语言中没有传递引用的方式,但是指针p“指向”变量i,并且你通过传递指针p的值来完成操作。
在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
p是一个指针变量,它的值是i的地址。当你调用f时,你传递了p的值,也就是i的地址。
&
符号),并在函数内显式地取消引用(使用*
符号)。 - Chris Dodd