我想知道为什么 C99 允许在不兼容的指针类型之间进行转换:
void f(int* p)
{
}
void c(char* p)
{
f(p);
}
C11 是否也允许它们?诊断此类转换是否需要符合要求的实现?
我想知道为什么 C99 允许在不兼容的指针类型之间进行转换:
void f(int* p)
{
}
void c(char* p)
{
f(p);
}
C11 是否也允许它们?诊断此类转换是否需要符合要求的实现?
C99 不允许不同类型的指针之间的隐式转换(除了 to/from void*
)。这是 C99 基本原理所说的:
在没有显式转换的情况下,将指向任何类型对象的指针转换为指向不同类型对象的指针是无效的。
这是赋值规则的结果,它具有以下约束之一(当涉及指针时)(C99 6.5.16.1“简单赋值”):
- 两个操作数都是指向兼容类型的限定或非限定版本的指针,并且左边指向的类型具有右边指向的类型的所有限定符;
- 一个操作数是指向对象或不完整类型的指针,另一个是指向 void 的限定或非限定版本的指针,左侧指向的类型具有右侧指向的类型的所有限定符;
- 左操作数是指针,右操作数是空指针常量
将指针作为参数传递给原型函数遵循相同的规则,因为(C99 6.5.2.2/7 “函数调用”):
如果表示被调用函数的表达式具有包含原型的类型,则参数将隐式转换为相应参数的类型,就像通过赋值一样
C90 和 C11 都有类似的措辞。
我相信许多编译器(包括 GCC)放宽了这个限制,只发出警告,因为有太多依赖它的遗留代码。请记住,这void*
是 ANSI C 标准的发明,因此是标准前的,可能还有很多标准后的代码,通常使用char*
或int*
作为“通用”指针类型。
没有“不兼容”的指针类型之类的东西。
C 的美妙之处在于它允许程序员做他们想做的事。由程序员决定什么是兼容的还是不兼容的。其他声称强制“ class
”或“ type
”内聚的语言以有限的方式这样做。允许引用对象的那一刻使用了指针,并且可能会出现类管理不善。