我正在编写一个C程序,如下所示,我为变量赋值 由全局指针指向,该指针由赋值右侧的函数调用更改。
但是更改发生在它之前指向的位置。 因此,对于以下代码,它会打印
“GP:5 P:5 GPV:11”,
应该在哪里
“GP:10 P:10 GPV:9”
我尝试用-O2和-O0进行编译。相同的输出。
我知道如果我将分配分成2行就可以解决问题。但我正在研究的项目有很多这样的地方。
这是否可以让它像我想要的那样工作而不会将其分成两行?
任何建议都受到高度赞赏。
#include <stdio.h>
int * gp;
// volatile int *gp; // I tried these two.
// int * volatile gp; // Didn't help.
int func(int *p)
{
*p = 5;
gp = p;
return *p;
}
int main()
{
int p = 7;
int gp_v;
gp = &gp_v;
*gp = 8;
*gp = func(&p) + *gp;
gp_v ++;
printf("GP:%d P:%d GPV:%d\n", *gp, p, gp_v);
return(0);
}
答案 0 :(得分:2)
此行有未指定的行为:
*gp = func(&p) + *gp;
C标准没有指定在表达式中计算参数的顺序,因此编译器可以在读取func(&p)
之前或之后执行*gp
来计算添加。同样,它可以在评估其存储的值之前或之后评估赋值左侧的*gp
(以确定存储结果的地址)。
您需要将语句分解为单独的语句,以使其具有明确定义的行为。这些都可以工作,但它们有不同的语义:
// Option 1: write to old location of *gp
int *old_gp = gp;
int old_gp_val = *gp;
*old_gp = func(&p) + old_gp_val;
// Option 2: write to new location of *gp
int old_gp_val = *gp;
int new_val = func(&p) + old_gp_val;
*gp = new_val;
答案 1 :(得分:1)
要将它保持在一行,你必须把它包起来:
#include <stdio.h>
int * gp;
int funcPlus(int *p, int *pGlobal)
{
func(p); // alters the value of *pGlobal
return *p + *pGlobal; // use the new value
}
int func(int *p)
{
*p = 5;
gp = p;
return *p;
}
int main()
{
int p = 7;
int gp_v;
gp = &gp_v;
*gp = 8;
// *gp = func(&p) + *gp; // undefined behavior
*gp = funcPlus(&p, gp);
gp_v ++;
printf("GP:%d P:%d GPV:%d\n", *gp, p, gp_v);
return(0);
}