理解 C 语言中的复杂表达式



请帮我理解以下表达式:

(在一本书中看到)

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

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

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

(int *)marksmarks(无论那是什么)解释为指向int的指针,那么我们得到了i++添加的结果。此指针被取消引用,i+1分配给相应的对象。

此表达式没有定义的行为,因为它读取和修改两个不同的子表达式i,这两个子表达式未先于另一个排序。

烧掉书。

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

注意:正如其他人所说,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;

提到的表达式会产生未定义的行为

C99 6.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

您可以查看:未定义的行为和序列点以及:)

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

*((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的值),这意味着您将根据平台,优化设置甚至周围的代码获得不同的结果。 语言标准显式地未定义行为,以便编译器不需要以任何特定方式处理此代码。 你会得到一个结果,但不能保证它在编译器之间(甚至从运行到运行)是一致的。

(int *)marks

将标记转换为整数指针

+ i++

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

*(...) = i+1

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

我希望这是一个示例,例如您不应该如何编写代码:)

让我们看看。

*((整数 *)标记 + i++) = i+1

-标记被强制转换为指向
int-i 的指针递增 1-指针 (
int *)标记使用指针算法按值 (i+1) 前进
- 此指针现在被取消引用,所以...
-...它指向的内存位置现在以 i+1 的值写入

最新更新