我在语言C中有一个问题。考虑以下代码(这是一个最小的例子):
#include <stdio.h>
int f(int**, int*);
int main(int argc, char *argv[])
{
int *u = NULL, t1=0, t2=1;
u = &t1;
printf("t1 : %d\n", t1);
printf("t2 : %d\n\n", t2);
*u = 36;
printf("t1 : %d\n", t1);
printf("t2 : %d\n\n", t2);
*u = f(&u, &t2);
printf("t1 : %d\n", t1);
printf("t2 : %d\n\n", t2);
return 0;
}
int f(int** p, int* e){
*p = e;
return 24;
}
当我运行此程序时,我得到以下结果:
t1 : 0
t2 : 1
t1 : 36
t2 : 1
t1 : 24
t2 : 1
令我惊讶的是表达式的左侧部分(即* u):
*u = f(&u, &t2);
在处理函数f之前固定。 事实上,我期待以下结果,因为函数f修改了指针u:
t1 : 0
t2 : 1
t1 : 36
t2 : 1
t1 : 36
t2 : 24
这是正常的吗?我在C班中错过了什么?
答案 0 :(得分:5)
赋值表达式中没有序列点,并且在赋值表达式的左右操作数之间没有保证的评估顺序。您编写的代码在C中没有明确定义的行为,因此您看到的行为并不意味着您的编译器不符合。
6.5 / 3:
除非稍后指定(对于函数调用
()
,&&
,||
,?:
和逗号运算符),否则子表达式的评估顺序和发生副作用的顺序都是未指明的。
虽然函数调用中有一个序列点,但无法保证在评估*u
之前或之后调用该函数。
答案 1 :(得分:0)
运行代码后,我得到了您所期望的答案。您应该更仔细地检查您的代码。
编辑:看完其他答案后,我觉得我应该发布我的规格。我在Windows 7 Ultimate 64位上运行Visual Studio 2010 64位。
答案 2 :(得分:0)
调用该函数时,将存储返回值的存储器位置是固定的。 虽然您正在更改指向的内容,但函数调用中发生的分配(内存位置)已经修复。
事实上,如果你试试
#include <stdio.h>
int f(int**, int*);
int main(int argc, char *argv[])
{
int *u = NULL, t1=0, t2=1;
u = &t1;
printf("t1 : %d\n", t1);
printf("t2 : %d\n\n", t2);
*u = 36;
printf("t1 : %d\n", t1);
printf("t2 : %d\n\n", t2);
*u = f(&u, &t2);
printf("t1 : %d\n", t1);
printf("t2 : %d\n\n", t2);
printf("u : %d\n\n", *u);
return 0;
}
int f(int** p, int* e){
*p = e;
return 24;
}
你会得到
t1 : 0 t2 : 1 t1 : 36 t2 : 1 t1 : 24 t2 : 1 u : 1
答案 3 :(得分:0)
嘿,它不是任何ABNORMAL行为,编译器正常工作。
*u = f(&u, &t2);
int f(int** p, int* e)
{
*p = e; // It means value of t2 gets copied into memory location pointed by u i.e t1
return 24; // Now this 24 would get stored/overwrite in memory location pointed by u i.e t1
} // Thus no change occurs in t2
记住功能“f”仅对由U指示的存储位置的值进行更改,而不是由u指示的地址。