免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: MMMIX
打印 上一主题 下一主题

[C] 拨开迷雾见真知--C语言中指针的使用(获奖名单已公布-2014-4-21) [复制链接]

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
91 [报告]
发表于 2014-04-15 12:48 |只看该作者
说点闲话,说说为什么C标准里要规定这些指针转换的“合法性”规则。
假定有一个CPU规定,所有尺寸为n字节的基本类型必须在内存中按照n字节对齐(比如说4字节整数一定要放在4字节边界上)否则就会出错(这不是纯虚构,很多RISC有类似的限制),那么一个“合法”的编译器(或者CPU本身)可以做这样的事
1、强制要求所有的int32_t指针最后两个bit为0
2、任何类型转换到int32_t *时,主动将最后两个bit清0
3、等值比较int32_t *和其它数据时,忽略最后两个bit
牢记一点,上述所有行为都是完全符合C标准的,因为如果想在这种体系结构上实现C,C的标准必须能包容这些行为。
如果你的程序不规范,就会产生一些古怪的结果,比如

  1. char *p1="hello";
  2. int *p2=p1;
  3. char *p3=p2;
  4. assert(p1==p3);
复制代码
上述代码可能会失败,因为p1可能是在1字节边界上对齐的,比如0x00012345,转换到p2就变成了0x00012344,和p1已经不相等了。
在这样的环境下,C标准中的void *就是用来保证上述事情不会发生,下面的代码是合法的

  1. char *p1="hello";
  2. void *p2=p1;
  3. char *p3=p2;
  4. assert(p1==p3);
复制代码
因为C标准要求void *必须能“无损”地容纳其它类型的指针,但并没有对int *有这样的要求。

对于函数指针,C标准规定任何函数指针都能“无损”地容纳任何其它类型的函数指针,其实背后的原因是,目前为止,没有任何一个有实际应用的体系架构对代码的对齐有强制性要求,比如要求add指令一定要在2字节边界上否则就会SIGBUS之类。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
92 [报告]
发表于 2014-04-15 13:04 |只看该作者
回复 91# OwnWaterloo

Linux内核和Windows API里那些不太规范的用法,说明“可移植性”的实际边界其实有限。
对于Linux内核来说,它所需要适应的编译器其实只有一个,就是GCC,所以它根本不需要考虑对其它编译器的支持,而且针对GCC这个特定的编译器,就连我们常说的UB也变成了确定行为,Linux内核所面对的“可移植性”其实是各个不同的CPU/体系架构,它的开发者才不会在意其它编译器会不会报错,君不见ICC/Clang反倒都以能成功编译Linux内核为荣么?
同样,整个Windows API需要面对的编译器也只有VC,只要VC支持,Windows API可以随意违反C的任何标准,反正Windows也没法用其它任何编译器编译出来,反正想要生成Windows EXE你就得兼容VC的行为……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP