反映赋值操作左侧全局指针的变化

时间:2012-10-03 16:45:23

标签: c pointers

我正在编写一个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); 
}

2 个答案:

答案 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); 
}