C中表达式的指针和正确评价

时间:2011-02-15 07:57:09

标签: c pointers

我在语言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班中错过了什么?

4 个答案:

答案 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指示的地址。