#include <stdio.h>
int inc1(int x) { return x++; }
int inc2(int *x) { return (*x)++; }
int
main(void)
{
int a;
a = 3;
printf("%d\n", inc1(a) + a);
printf("%d\n", inc2(a) + a);
return 0;
}
我正在处理过去的一篇论文,其中一个问题是跟踪第6行和第9行之间的变化。我有点理解指针(引用内存位置)但是如果有人可以通过对这段代码所做的更改很棒。
答案 0 :(得分:3)
我将解释这个几乎完全没有错误的代码:
#include <stdio.h>
int inc1(int x) { return x++; }
int inc2(int *x) { return (*x)++; }
int main(void) {
int a;
a = 3;
printf("%d\n", inc1(a) + a);
printf("%d\n", inc2(&a) + a);
return 0;
}
a
被初始化为3,然后将的值传递给inc1()
,后者返回它并使用后增量。这意味着返回的实际值仍为3.
接下来,将的地址传递给inc2()
。这意味着x中的值发生了什么。同样,使用了后增量,因此inc2()
返回的是3,但在调用之后,a
为4。
但是,编译器可以按序列点之间的任意顺序自由评估表达式,例如a
或inc2(&a)
。这意味着a
右侧的inc2(&a) + a
可能是3或4(取决于a
之前或之后是否评估int2(&a)
,因此程序可能会输出 6 7 或 6 6 。
答案 1 :(得分:0)
调用inc1()的行将打印'6'(3 + 3)[前3是来自inc1(),由于后增量运算符,不返回增量值]。此外,由于inc1()由值调用,因此“a”的值不会影响函数外部。
现在,如果论文中调用 inc2()的声明如下:
printf("%d\n", inc2(a) + a);
然后你的代码将编译(希望你将内存位置存储在'a'中)但是在运行时取决于其中的值(在'a = 3'的情况下)你会得到Segmentation Fault,因为你正在尝试取消引用程序不应该访问的内存位置3。
或者,如果声明如下:
printf("%d\n", inc2(&a) + a);
然后inc2()将通过指针(地址)递增'a'的值,但是由于使用了后递增运算符,它仍将返回'a'(3)的旧值,但它仍然会增加'a'并且任何后续访问'a'都将获得新值。下一个'a'将具有值'4',因为评估是从左到右完成的,因此它将打印7(3 + 4)。
我希望它能澄清C中指针和变量之间的区别。