Re: [问题] 关于函数指标的参数型别转型

楼主: littleshan (我要加入剑道社!)   2017-06-26 22:32:58
: ※ 发信站: 批踢踢实业坊(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 的规范。
作者: a27417332 (等号卡比)   2017-06-26 23:43:00
感谢大大的回答!不过我还是有点好奇我是不是读错意思以https://goo.gl/4i7oTh的6.2.5的27条来说,指出它们两个要有一样的representation,根据底下的注脚,这个representation跟binary representation是两回事吗?不太理解这里的互换性是什么意思?了解了,感谢!所以原本那篇strcmp的问答后面其实是肯定句?因为两个值必须相等。不过总觉得看标准对于function pointer的解释,好像就一定要两个指标所指向的物件是相容的。但他提到相容的状况只有同样型别和不同编译单元中满足条件的struct所以我可以理解成其实标准对于这样转型的行为是未定义吗?(上面提到的"两个指标所指向..."是指function pointer的parameter type,感觉我描述的好模糊QQ)
楼主: littleshan (我要加入剑道社!)   2017-06-28 23:11:00
对,我的看法是标准对于转型后呼叫不做任何保证
作者: a27417332 (等号卡比)   2017-06-29 12:34:00
感谢大大的回答了!

Links booklink

Contact Us: admin [ a t ] ucptt.com