c - C - 不兼容的指针类型分配:为什么它是一个警告?
问题描述
我正在看 K&R 第 2 版,它说(在第 5.4 节中):
除了 void *,将一个类型的指针分配给另一种类型的指针而不进行强制转换是不合法的。
但是,gcc 和 clang 在执行此操作时只会发出警告,而不是编译器错误:
int *ip;
char *cp;
ip = cp;
我在 gcc 手册上没有看到任何说明这是默认编译器扩展的内容。使用 C++ 编译器确实会引发编译错误。
请注意,这本书在 A6.6 节中似乎自相矛盾,它说
指向一种类型的指针可以转换为指向另一种类型的指针。
尽管我给了它怀疑的好处,因为它可能指的是使用显式强制转换从指针类型转换为另一种。
解决方案
int *ip;
char *cp;
ip = cp;
赋值是违反约束的,这意味着符合标准的编译器必须发出诊断,就像它必须为语法错误所做的那样。(有关简单分配的要求,请参阅http://port70.net/~nsz/c/c11/n1570.html#6.5.16.1。)该诊断可能是非致命警告。C 标准从不要求拒绝代码,除非它有#error
指令。它没有将代码称为“合法”或“非法”。
如果您使用例如gcc -std=c11 -pedantic-errors
. 请注意,默认情况下 gcc 不是完全符合标准的 C 编译器,尽管在这种情况下它的行为是符合标准的。
通过强制转换(显式转换),分配将是合法的:
ip = (int*)cp;
但如果 的值cp
不确定或转换导致无效int*
值(例如由于对齐),则可能会导致未定义的行为。
K&R 中的描述是正确的,尽管措辞有点不正式。它说:
除了 void *,将一个类型的指针分配给另一种类型的指针而不进行强制转换是不合法的。如果“合法”是指“不违反约束或语法规则”,这是正确的。C 标准本身并没有使用“合法”这个词,但是说某事违反了约束就等于说某事是非法的。
是的,这个:
指向一种类型的指针可以转换为指向另一种类型的指针。确实是指使用强制转换的转换——或者在转换为和从的情况下不使用强制转换
void*
。
(我个人的偏好是将语法错误和约束违规视为致命错误,但大多数编译器默认情况下相对宽松。这可能是出于历史原因。在语言的早期版本中,将一种类型的指针分配给没有强制转换的另一种类型的指针是有效的,并且从来没有一个好时机通过拒绝旧代码来破坏它。)
推荐阅读
- ios - Whatsapp 打开 url 代码在 ios 中打开 Boltt Health App 而不是 whatsapp
- java - 无法创建具有动态值的条件查询
- python-3.x - 如何将 python 版本 3.5.6 安装到 ubuntu/Linux 中?
- sql-server - 避免逗号分隔的 sql 查询中的重复值
- c# - 比较 C 和 C# 中的程序集
- python - 如何在odoo 10中设置一个模型的多个视图?
- xamarin - 即使应用程序在 Xamarin (Android) 中关闭,如何创建应用程序服务始终在后台运行的应用程序?
- javascript - 打字稿-“...不是函数或其返回值不可迭代”
- rangeslider - 知道在 rangeslider.js 中是否手动或以编程方式更改了滑块值?
- c# - 如何停止 log4net 记录并释放最后一个文件