c语言 - 如果某些限制指针指向同一对象,为什么编译器不会生成警告或错误?



如果有一个函数:

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将是相同的对象。但是为什么这段代码可以编译成功呢?

restrict基本上是程序员对编译器的一个承诺,即指针是唯一用来访问它所指向的对象的指针(在指针的作用域内)。

编译器(通常)不会检查这个承诺——它把这个责任留给了程序员。如果程序员做错了,未定义的行为将受到惩罚。

一般不可能检测到这种类型的UB。调用函数可能已经从另一个编译单元接收了指针。这就是为什么在一般情况下这是"只是"UB,因为作为一个约束,它不能在编译时被检测到。

在这种情况下,没有什么可以阻止编译器发出诊断。为什么您的编译器实现者认为不值得实现这样的诊断,您必须在那里直接询问。

restrict的全部意义在于告诉编译器,它可以假设受限制的指针指向的内存与在该点可访问的任何其他内存之间没有重叠,这样编译器就可以在没有这种假设的情况下进行优化。如果编译器自己可以判断出没有这样的重叠,那么就不需要这个关键字了。将func中的代码设置为错误将破坏关键字的全部目的。至于func的调用:由于编译器通常无法判断是否违反了限制,因此不需要注意它可以判断的实例。一些高质量的编译器,在适当设置了警告级别的情况下,可能会发出警告,例如您问题中的func调用。

这段代码可以成功编译,因为它没有任何错误。
简单地说,它是一个符合标准的代码。标准只要求对格式不良的代码进行诊断,而这段代码不是。

这就像,你可以朝自己的头开枪,但这并不意味着你应该这样做,如果你这样做了,你只能怪你自己,而不是别人没有阻止你这样做。

相关内容

最新更新