“restrict”是否会影响传递到其他对象的指针的别名
添加到C99中的“restrict”是否会影响传递到其他对象的指针的别名,c,language-lawyer,restrict,strict-aliasing,restrict-qualifier,C,Language Lawyer,Restrict,Strict Aliasing,Restrict Qualifier,添加到C99中的restrict关键字的一个主要用途是允许编译器将某些内容加载到寄存器中,并假设寄存器将镜像这样加载的变量的状态。给定 void foo1(int * restrict a, int * restrict b) { (*a)++; (*b)++; (*b)+=(*a); } 编译器有权假定写入(*b)不会影响(*a),从而避免在写入(*a)后重新加载(*a)。restrict对别名是否有其他影响?例如,假设: extern void foo2a(int * restrict
restrict
关键字的一个主要用途是允许编译器将某些内容加载到寄存器中,并假设寄存器将镜像这样加载的变量的状态。给定
void foo1(int * restrict a, int * restrict b) {
(*a)++; (*b)++; (*b)+=(*a);
}
编译器有权假定写入(*b)
不会影响(*a)
,从而避免在写入(*a)
后重新加载(*a)
。restrict
对别名是否有其他影响?例如,假设:
extern void foo2a(int * restrict q);
extern void foo2b(void);
int x;
int foo2(restrict int *q) {
int z=x;
x++; *q++; x++;
foo2a(&z);
x++; *q++; z++;
foo2b();
x++; *q++; z++;
return x+(*q)+z;
}
编译器是否需要预测*q
的增量以及对foo2a()
和foo2b()
的调用可能都干扰了x
,并且调用可能对x
和*q
的值“感兴趣”?编译器是否需要假定对foo2a()
的调用可能保留了它的参数——即使它被标记为restrict
,以便foo2b()
可以修改z
如果编译器需要在最坏情况下运行,尽管有
restrict
关键字,有没有办法授予编译器权限,允许其忽略在函数调用之前存储对某些变量的任何更改并在下次需要时重新加载的任何正常义务?只回答标题中的问题:是。restrict
限定指针意味着您可以保证只有通过该指针才能访问整个对象。这也意味着它不能与相同类型的文件范围对象别名,例如
对于问题的其余部分,您正在混合各种内容<代码>限制绝不是调用者的保证。调用方甚至没有“看到”restrict
关键字,类型限定不是接口的一部分。因此,从调用返回时,文件范围变量是否已更改与restrict
无关
restrict
只是调用者向被调用者提供的一种保证,被调用者随后可以在内部使用该信息进行优化。不能对t1==t2
问题进行优化,因为两者都可能是空指针,必须进行相等的比较。@EOF:给定编辑,编译器是否可以省略t1==t2
检查?我相信可以,但不久前我尝试了这个方法,并且无法让gcc或clang删除检查,即使对于不兼容的类型也是如此。gcc省略检查的唯一方法是显式的if(a==b)\uuu内置的\uu不可访问()
。依靠它是否是一个好主意是另一个问题。不,不应该restrict
访问不同对象需要限定指针,但如果t1
或t2
未取消引用,或者如果使用不相交的偏移集取消引用,则它们可以相等,而不违反restrict
关键字隐含的要求。例如,memcpy(p,p,0)代码>非常好。@chqrlie:好的,谢谢你的帮助。我想知道我是否应该去掉问题的最后一点,以帮助将注意力集中到第一点?因此参考这个例子,*q
不能别名x
,但是foo2a
和foo2b
都可以自由修改*q
、x
和z
[第一个原因是指针的副本可以合法地存在于全局变量中;第二个原因是它是全局变量,第三个原因是foo2a
可以合法地隐藏&z
?]的副本]是的,我想是的,一旦你在一个不透明的函数调用中泄露了一个变量的地址信息,你就永远无法确定其他函数对这个变量做了什么。我想知道C是否会标准化任何区分保留指针和非保留指针,或纯函数和纯函数的方法?我认为编译器是武装起来的有了一定的知识,我们可以进行一些目前还不符合标准的实质性优化。考虑到这一点,我不太确定保存restrict
指针的副本是否符合犹太教义,除非是在非常狭窄的情况下(例如,restrict
指针在作用域内时,不会写入任何对象,也不会写入通过restrict
指针访问的对象)。如果restrict
的功能是指持有该指针的代码可能会急切地从中读取任何最终将被读取的内容,或者可以在没有副作用的情况下读取(例如seg故障),并且写操作可能会推迟到允许其他对象读取相同的位置……我不太清楚,如果通过将受限制指针复制到其原始范围之外来延长其生存期,这会受到什么影响。