如果我们有一个功能:
void func(int *restrict a, int *restrict b, int *restrict c) {
*c = *a + *b;
}
原则上,此代码可能会导致一些错误:
int aa = 1;
func(&aa, &aa, &aa);
因为在func
中,*a
*b
*c
将是同一个对象。但为什么这个代码可以成功编译?
答案 0 :(得分:4)
restrict
基本上是程序员对编译器的承诺,指针是唯一一个用于访问它指向的对象的指针(在指针范围内)。
编译器(通常)不检查该承诺 - 它将责任留给程序员。如果程序员弄错了,那么未定义的行为就是惩罚。
答案 1 :(得分:2)
通常,不可能检测到这种类型的UB。调用函数可能已经从另一个编译单元接收指针。这就是为什么通常这只是“UB”,因为作为约束,它在编译时无法检测到。
但是,在这种情况下,没有什么能阻止编译器发出诊断。为什么你的编译器实现者没有发现实现这种诊断的价值,你必须直接在那里询问。
答案 2 :(得分:1)
restrict
的重点是告诉编译器它可以假设受限指针所指向的内存与此时可访问的任何其他内存之间没有重叠,因此编译器可以进行优化没有这样的假设就不可能。如果编译器可以告诉自己没有这样的重叠,那么就不需要关键字。使func
中的代码成为错误会破坏关键字的整个目的。至于func
的调用:由于编译器通常无法判断是否违反了限制,因此不需要记录它可以告诉的实例。某些高质量编译器(警告级别设置正确)可能会在您问题中func
调用等情况下发出警告。
答案 3 :(得分:0)
此代码可以成功编译,因为它没有任何错误 简单地说,它是一个符合标准的代码。该标准要求仅对格式错误的代码进行诊断,而此代码则不需要。
它是一样的,你被允许射击自己的头脑,并不意味着你应该,如果你只做,你应该责怪别人没有阻止你这样做。