理解C中的复杂表达式

时间:2014-01-27 14:02:16

标签: c increment dereference

请帮助我理解以下表达式:

(见一本书)

*((int *)marks + i++) = i+1

大量的增量和符号引用令人困惑!

7 个答案:

答案 0 :(得分:5)

我希望这本书有一个不好的例子,因为它的行为是未定义的。

(int *)marksmarks(无论可能是什么)解释为指向int的指针,然后我们将i++的结果添加到该i+1。取消引用此指针,并将i分配给相应的对象。

此表达式没有已定义的行为,因为它在两个不同的子表达式中读取和修改{{1}}。

答案 1 :(得分:5)

烧掉这本书。

由于没有序列点,语句的行为是未定义。一个更简单的理解案例是i++ = i,它也是未定义的。

答案 2 :(得分:0)

注意:正如其他人所说,i++表达式是未定义的行为。在g ++中,i++操作将按如下方式执行:

// Pointer to some data.
void* marks = ???;
// Typecast to an integer pointer
int* marksIntPointer = (int*)marks;
// Move the position in memory. I am assuming that 'marks' is an array.
int* marksIntPointerOffset = marksIntPointer + i;
// Undefined behaviour, could take place here or before, depending on the compiler (as others have said).
i++;
// Set the value of the desired memory.
*marksIntPointerOffset = i+1;

答案 3 :(得分:0)

上述表达式产生 未定义的行为

C996.5§2陈述:

  

1)在前一个和下一个序列点之间,一个对象应具有其存储的值   通过表达式的评估最多修改一次。

     

2)此外,只读取先前值以确定要存储的值


1)在单个表达式中存储和修改变量的值非常简单:

i = ++i;
i++ = i;
++i = 7;

以及在单个表达式中多次修改同一变量的值:

j = ++i + ++i;

2) 只读以确定要存储的值 可能有点棘手。这意味着即使以下(就像前面的例子一样)也会调用未定义的行为

j = (i + 1) + i++;
a[i++] = i;  
*(ptr + i++) = i;

以及:

*((int *)marks + i++) = i+1

您可以查看:Undefined behavior and sequence points:)

答案 4 :(得分:0)

正如其他人所说,行为未定义;通过删除++运算符,以下代码将被很好地定义(但仍然像罪一样丑陋):

*((int *)marks + i) = i+1

以下是它如何分解:

         marks               -- take the expression marks
  (int *)marks               -- cast it as a pointer to int
  (int *)marks + i           -- offset i integer elements from that address
*((int *)marks + i)          -- deference the result to get an array element
*((int *)marks + i) = i+1    -- assign the result of i+1 to that element

这主要是将marks视为int的数组,并将i+1的结果分配给i元素:

int *mp = (int *) marks;
mp[i] = i+1

原始表达试图

mp[i++] = i+1

调用未定义的行为。由于未指定评估i++i+1的顺序;编译器可以按任何顺序自由评估它们。由于i++有副作用(更新i的值),这意味着您将根据平台,优化设置甚至周围的代码获得不同的结果。语言标准明确地保留行为 undefined ,以便编译器不需要以任何特定方式处理此代码。您将获得一个结果,但不保证从编译器到编译器(甚至从运行到运行)都是一致的。

答案 5 :(得分:-2)

(int *)marks

将标记转换为int指针

+ i++

在标记处添加i(查找指向的地址)然后将i递增1

*(...) = i+1

设置我们的指针指向i + 1的单元格的VALUE(注意我之前已经增加的事实,因此在指令开始时它将大于2。

我希望这是一个不应该编写代码的例子:)

答案 6 :(得分:-2)

让我们看看。

*((int *)marks + i ++)= i + 1

-marks被强制转换为指向int
的指针 -i增加1 - 使用指针运算
使指针(int *)标记前进值(i + 1) - 这个指针现在被解除引用,所以......
-...它指向的内存位置现在用i + 1

的值写入