作者littleshan (我正在想要换什麽)
看板C_and_CPP
标题Re: [问题] 关於函数指标的参数型别转型
时间Mon Jun 26 22:32:58 2017
:
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 36.229.13.151
: ※ 文章网址: https://webptt.com/cn.aspx?n=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 的规范。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 36.225.52.224
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1498487581.A.281.html
1F:推 a27417332: 感谢大大的回答!不过我还是有点好奇我是不是读错意思 06/26 23:43
3F:→ a27417332: 它们两个要有一样的representation,根据底下的注脚, 06/26 23:44
4F:→ a27417332: 这个representation跟binary representation是两回事 06/26 23:45
5F:→ a27417332: 吗?不太理解这里的互换性是甚麽意思? 06/26 23:48
Sorry 你是对的,我忘了 C 对 char* 是有特别保证的
因此我稍微修改了文章中的范例
void* 与 char* 的 representation 相同,是否表示他们是 compatible type?
依照标准的逻辑,compatible type 必需要有相同的 representation
但反过来是否成立,老实说我不知道 orz
如果是,表示 strcmp 可以转型後传入 qsort (前提是排序对象为二维阵列)
但就算可以,我也不是很想看到大家真的这样用
※ 编辑: littleshan (36.225.52.224), 06/27/2017 00:50:27
6F:→ a27417332: 了解了,感谢! 06/27 21:23
7F:→ a27417332: 所以原本那篇strcmp的问答後面其实是肯定句?因为两个 06/27 21:25
8F:→ a27417332: 值必须相等。 06/27 21:25
9F:→ a27417332: 不过总觉得看标准对於function pointer的解释,好像就 06/27 21:26
10F:→ a27417332: 一定要两个指标所指向的物件是相容的。但他提到相容的 06/27 21:27
11F:→ a27417332: 状况只有同样型别和不同编译单元中满足条件的struct 06/27 21:27
12F:→ a27417332: 所以我可以理解成其实标准对於这样转型的行为是未定义 06/27 21:28
13F:→ a27417332: 吗? 06/27 21:28
14F:→ a27417332: (上面提到的"两个指标所指向..."是指function pointer 06/27 21:29
15F:→ a27417332: 的parameter type,感觉我描述的好模糊QQ) 06/27 21:30
16F:→ littleshan: 对,我的看法是标准对於转型後呼叫不做任何保证 06/28 23:11
17F:推 a27417332: 感谢大大的回答了! 06/29 12:34