: ※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 36.229.13.151
: ※ 文章网址: https://www.ptt.cc/bbs/C_and_CPP/M.1498401215.A.09D.html
: 推 littleshan: compatible type有严格的定义,基本上就是相同的type 06/25 23:13
: → littleshan: “可以互转”并不表示它们是compatible type 06/25 23:13
:
: 原来如此!
: 另外想再问一下这篇:https://goo.gl/VnXBVn
: 为什么这篇底下说如果满足那个转型的假设,就可以让这个转型的行为符合预期?
: 印象中任何非函数指标转到char*,都是可行的。
: void*和char*的对齐要求有可能不一样吗?
: (参考自这篇:https://goo.gl/UyQr15)
:
: 还麻烦各位大大了,感激不尽m(_ _)m
趁这机会回一下好了
这边算是许多 C 使用者常见的误解
对某个物件进行转型时,C 并不保证底层的 binary representation 是相同的。
举个例子:你可以把 int 转成 double,再把同一个 double 转回成 int
在大多数的平台上,因为 double 的精度够用,所以转过去再转回来的值是相同的。
但这是否表示 int 和 double 使用相同的位元格式来储存资料?当然不是。
纯粹只是 compiler 帮你做了一种可逆的格式转换
所以,如果你宣告一个 function 其参数是吃 double*,
但你却直接传递一个 int* 给它,尽管 int 可以安全地转换成 double,
但是 function 内并不知道进来的其实是 int*,其结果为 undefined behavior。
那么指标呢?比如说 void* 与 int* 的确可以互转,
但 C 标准从未明说他们使用相同的 binary representation。
假设有一个 compiler 在看到 int* 转成 void* 时,把内容做了 binary not
然后从 void* 转回 int* 时,又做了一次 binary not
那么这个 compiler 确实可以满足 C 标准中,
“指标转型至void*再转回原本型别时,可取得原值”的规定。
“太扯了吧!真的有这么恶搞的 compiler 吗?”
很不幸地,许多作业系统并不使用线性的内存空间
比如说这个例子 http://c-faq.com/null/machexamp.html
在这个系统上,你写 void* p = (void*)0 时,
compiler 实际上会在 p 的内容填入 07777:0
当然,现在的主流作业系统并没有这种奇葩的设计,
大部份的平台上 void* 与 int* 的 binary representation 是相同的,
但你只要做了这个假设,自己心里就得有个底,这已经打破了 portable 的规范。