我对限制指针的规则感到有些困惑。也许有人可以帮助我。
定义嵌套的受限指针是否合法如下:
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();
}
如下导出受限指针值是合法的:
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();
谢谢! 安德鲁
答案 0 :(得分:4)
作为参考,这里是restrict
限定符的相当复杂的定义(来自C99 6.7.3.1“限制的正式定义”):
让p成为普通人的宣言 提供手段的标识符 将对象P指定为 限制限定指针指向类型T.如果D出现在一个区块内 没有存储类 extern,让B表示块。如果D 出现在参数列表中 函数的声明 定义,让B表示 相关块。否则,让B 表示主要块(或块) 任何函数的调用 程序启动独立式 环境)。
在下文中,指针 表达式E据说是基于 对象P if(在某个序列点 在执行B之前 评估E)将P修改为点 将数组对象的副本放入 以前指出的会改变 E的值。注意“基础”是 仅为表达式定义 指针类型。
在每次执行B期间,让L为 任何具有&amp; L基于P的左值。如果 L用于访问的值 它指定的对象X,X是 也修改(通过任何方式),然后 以下要求适用:T应 不是const限定的。所有其他 左值用于访问X的值 也应以其地址为基础 P.每次修改X的访问都应该 也被认为是修改P,for 本条款的目的。如果P. 被赋予指针的值 表达式E基于另一个 限制指针对象P2, 与块B2相关联,然后是 B2的执行应在之前开始 执行B,或者 B2的执行应在此之前结束 分配。如果这些 要求不符合,那么 行为未定义。
这里B的执行意味着 部分执行的 与...对应的程序 具有标量类型的对象的生命周期 和自动存储持续时间 与B相关联。
我对上述内容的阅读意味着,在您的第一个问题中,a
无法分配到b
,即使在“子”块内 - 结果也未定义。如果在“子块”中声明了b
,则可以进行这样的分配,但由于b
被声明为与a
相同的范围,因此无法进行分配。
对于问题2,c
和d
之间的分配也会导致未定义的行为(在这两种情况下)。
标准中的相关位(对于这两个问题)是:
如果为P赋值a 指针表达式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 } }
答案 1 :(得分:1)
restrict
类型限定符是编译器的指示,如果修改了restrict
- 限定指针所寻址的内存,则其他指针不会访问该内存记忆。编译器可以选择优化涉及restrict
的代码 - 合格的指针,否则可能导致不正确的行为。 程序员有责任确保使用限制合格的指针,因为它们是打算使用的。否则,可能会导致未定义的行为。(link)
从上面的描述可以看出,你的任务都是非法的,可能在某些编译器生成的可执行文件中有效,但在其他编译器中则有效。不要指望编译器本身发出错误或警告,因为restrict
只是提供了执行某些优化的机会,它可以选择不执行,例如volatile
。