1

我正在编写一个如下所示的 C 程序,其中我将一个值分配给一个由全局指针指向的变量,该指针正在被赋值右侧的函数调用更改。

但是变化发生在它之前指向的位置。因此,对于以下代码,它会打印

"GP:5 P:5 GPV:11" ,

它应该在哪里

“GP:10 P:10 GPV:9”

我试过用-O2和-O0编译它。相同的输出。

我知道如果我将作业分成两行,它是固定的。但是我正在做的项目有很多这样的地方。

这是否可以让它像我想要的那样工作而不把它分成两行?

任何建议都受到高度赞赏。

#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); 
}
4

2 回答 2

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;
于 2012-10-03T17:18:27.917 回答
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); 
}
于 2012-10-03T17:30:31.583 回答