我对有关受限指针的规则有点困惑。也许有人可以帮助我。

  1. 如下定义嵌套受限指针是否合法:

    int* restrict a;
    int* restrict b;
    
    
    a = malloc(sizeof(int));
    
    
    // b = a; <-- assignment here is illegal, needs to happen in child block
    // *b = rand();
    
    
    while(1)
    {
        b = a;  // Is this legal?  Assuming 'b' is not modified outside the while() block
        *b = rand();
    }
    
  2. 按如下方式派生受限指针值是否合法:

    int* restrict c;
    int* restrict d;
    
    
    c = malloc(sizeof(int*)*101);
    d = c;
    
    
    for(int i = 0; i < 100; i++)
    {
        *d = i;
        d++;
    }
    
    
    c = d; // c is now set to the 101 element, is this legal assuming d isn't accessed?
    *c = rand();
    

谢谢!安德鲁

有帮助吗?

解决方案

作为参考,这里是 restrict 限定符相当复杂的定义(来自 C99 6.7.3.1“restrict 的正式定义”):

让 D 成为普通的宣言 标识符,提供 将对象 P 指定为 指向类型 T 的限制限定指针。

如果 D 出现在块内,并且 没有存储类 extern,设 B 表示块。如果 D 出现在参数列表中 函数的声明 定义,设 B 表示 关联的块。否则,让 B 表示 main 的块(或块 的任何函数被调用 在独立式中启动程序 环境)。

在下文中,指针 据说表达式 E 基于 对象 P if (在某个序列点 在执行 B 之前 评估 E) 将 P 修改为点 将数组对象复制到 它以前指出的会改变 E 的值。请注意,“基于”是 仅针对具有 指针类型。

在每次执行 B 期间,设 L 任何具有基于 P 的 &L 的左值。如果 L 用于访问 它指定的对象 X,X 是 也修改了(无论如何),然后 以下要求适用:T 应 不具有常量资格。每隔一个 lvalue 用于访问 X 的值 还应根据以下条件确定其地址 P.每个修改 X 的访问都应 也考虑修改 P,为 本款的目的。如果P 被分配指针的值 基于另一个的表达式 E 受限制的指针对象 P2, 与块 B2 关联,然后 B2 的执行应在 执行 B,或 B2 的执行应在 分配。如果这些 不满足要求,则 行为未定义。

这里执行 B 意味着 部分执行 对应于 具有标量类型的对象的生存期 和自动存储持续时间 与 B 相关。

我对上述内容的阅读意味着,在你的第一个问题中, a 不能分配给 b, ,即使在“子”块内 - 结果也是未定义的。如果可以进行这样的分配 b 是在那个“子块”中声明的,但是自从 b 声明的范围与 a, ,无法进行分配。

对于问题 2,之间的分配 cd 也会导致未定义的行为(在这两种情况下)。

标准中的相关部分(对于两个问题)是:

如果为 P 赋值 指针表达式 E,基于 另一个受限制的指针对象 P2, 与块 B2 关联,然后 B2 的执行应在 执行 B,或 B2 的执行应在 分配。

由于受限指针与同一块关联,因此块 B2 不可能在 B 执行之前开始,也不可能在赋值之前结束 B2(因为 B 和 B2 是同一块)。

该标准给出了一个例子,使这一点变得非常清楚(我认为 - 的清晰度 restrict 定义的 4 个短段落与 C++ 的名称解析规则相同):

实施例4:

限制分配之间的规则 受限制的指针不 区分函数调用 以及等效的嵌套块。除了一个例外,只有 “从外到内”的分配 嵌套中声明的受限制指针 块具有定义的行为。

{
    int * restrict p1;
    int * restrict q1;

    p1 = q1; //  undefined behavior

    {
        int * restrict p2 = p1; //  valid
        int * restrict q2 = q1; //  valid
        p1 = q2; //  undefined behavior
        p2 = q2; //  undefined behavior
    }
}

其他提示

restrict 类型限定符是 指示 向编译器表明,如果内存由 restrict-限定指针被修改,没有其他指针将访问同一内存。编译器可能会选择优化涉及的代码 restrict- 限定指针,否则可能会导致不正确的行为。 程序员有责任确保限制限定指针按其预期用途使用。否则,可能会导致未定义的行为。 (关联)

正如您从上面的描述中看到的,您的两个赋值都是非法的,这可能在某些编译器生成的可执行文件中有效,但在其他编译器中会中断。不要指望编译器本身会发出错误或警告: restrict 只是提供了执行某些优化的机会,它可以选择不执行,就像下面的情况一样 volatile.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top