【问题标题】:Confusion about undefined behaviour for restrict qualifier对限制限定符的未定义行为感到困惑
【发布时间】:2017-11-22 17:37:09
【问题描述】:

我在cppreference看到了下面的例子。

void f(int n, int * restrict p, int * restrict q)
{
    while(n-- > 0)
        *p++ = *q++; // none of the objects modified through *p is the same
                     // as any of the objects read through *q
                     // compiler free to optimize, vectorize, page map, etc.
}
void g(void)
{
    extern int d[100];
    f(50, d + 50, d); // OK
    f(50, d + 1, d); // Undefined behavior: d[1] is accessed through both p and q in f
}

在那个例子中,调用f(50, d + 50, d); 是可以的。

但是,我不明白,打电话给f(50, d + 1, d);是未定义的行为。为什么?

【问题讨论】:

  • 因为函数f中的对象d[1]是通过pq访问的。评论是这么说的。
  • 我不认为 restrict 在这里有帮助,因为“指针的生命周期”是函数调用 - 无论如何都会影响两个指针。正常的未定义行为适用
  • @MartinBeckett in function f 两个指针都受到限制,但在不同时间指向同一个对象。
  • @EugeneSh。 d 保存数组 d[0] 的基地址
  • @rsp 嗯什么? d 是一个数组。 d[0] 是一个数组元素。

标签: c undefined-behavior restrict


【解决方案1】:

指针上的restrict 限定符意味着通过该指针访问的任何被修改的对象在该指针的生命周期内都不会通过其他指针访问。换句话说,当一个对象通过指针p访问并在p的范围内修改时,那么它只能在该范围内通过p访问。违反此约束会导致未定义的行为。

f(50, d + 50, d);中,p将用于修改d[50]d[99]q将用于访问d[0]d[49]。没有重叠,所以一切都很好。

f(50, d + 1, d);中,p将用于修改d[1]d[50]q将用于访问d[0]d[49]。由于某些元素(例如d[1])是通过p 修改并通过q 读取的,因此这违反了restrict 限定符。

【讨论】:

  • 你好 interjay,所以当您通过别名指针访问对象或指针别名对象时,这是未定义的行为?您的陈述听起来只有当指向对象的指针被取消引用时才重要,并且只要它没有被取消引用,另一个指针是否别名并不重要?
  • ahhh 所以如果我有另一个指针别名受限指针只是为了保存地址然后将其恢复为受限指针,这不是未定义的行为吗?问题的原因是因为我正在处理堆栈VM并且指令指针受到限制,但操作码需要将指令指针值保存到堆栈。我担心这会导致 UB。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-16
  • 1970-01-01
  • 1970-01-01
  • 2020-08-04
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多