C 函数指针算法
为什么这段代码可以正确编译函数指针上的算术运算C 函数指针算法,c,pointers,C,Pointers,为什么这段代码可以正确编译函数指针上的算术运算 void my_func(void); int main(void) { void (*p)(void) = &my_func; // Compile (void) (*p); (void) *(p + 0); // Does not compile (void) p[0]; return 0; } 我一直认为p[0]=*(p+0)适用于完整类型。显然,p[0]!=*(p+0
void my_func(void);
int main(void)
{
void (*p)(void) = &my_func;
// Compile
(void) (*p);
(void) *(p + 0);
// Does not compile
(void) p[0];
return 0;
}
我一直认为p[0]=*(p+0)
适用于完整类型。显然,p[0]!=*(p+0)
用于函数指针
注意:C标准没有明确禁止函数指针算法。它一点也不禁止。它说它是未定义的。那是另一回事。许多符合标准条款的语言扩展都有标准未定义的行为
此外,如果使用指向不完整类型的指针,则我们有:
int main(void)
{
int (*p)[];
// Compile
(void) (*p);
// Does not compile
(void) *(p + 0);
(void) p[0];
return 0;
}
然后有效地
p[0]=*(p+0)
,因为两者都会在指向不完整类型的指针上触发相同的算术错误。尽管在这里,C标准明确禁止对指向不完整类型的指针进行算术运算。数组订阅a[b]
需要a
或b
中的一个作为指向完整对象类型的指针。函数类型不是完整的对象类型
6.5.2.1阵列订阅
约束条件
1其中一个表达式的类型为“指向完整对象类型的指针”,另一个表达式的类型为整数,结果的类型为“类型”
请注意,p+0
出于同样的原因也应该是一个错误,我认为编译器无法生成所需的诊断消息。我问这个为什么不生产:
6.5.6加法运算符
约束条件
对于加法,两个操作数都应具有算术类型,或者一个操作数具有算术类型
操作数应为指向完整对象类型的指针,另一个为
应具有整数类型。(增加等于增加1。)
你不能有函数指针算法-它是UB。我想知道第一件事是否可行,因为编译器实现了它的+0,并简单地将它从*(p+0)更改为*p。@anarrayofffunctions是的,你可以。它是由GCC和Clang作为扩展实现的。我不清楚为什么
p+0
会编译,因为+
的条件是两个参数都是算术类型,或者一个是指向完整对象类型的指针,所以我认为这个答案中缺少了一些东西。那么*(p+0)
编译只是因为这是一个由编译器处理的错误/警告,并且根据C标准仍然是未定义的行为?因为是,C标准明确禁止函数指针算术。@eigenslacker:C标准没有明确禁止函数指针算术。它一点也不禁止。它说它是未定义的。那是另一回事。许多符合标准条款的语言扩展都有标准未定义的行为。如果“未定义”意味着“禁止”,那就不可能了。它并不意味着“禁止”。@EricPostpischil我相信C标准确实禁止函数指针算法,编译器需要生成错误消息。我问了标准的链接。@Egenslacker我想你是对的,标准禁止它,但我认为编译器也需要生成诊断消息,因为它违反了约束。我问了这个问题,并链接到标准: