免费注册 查看新帖 |

Chinaunix

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

[C] 有多少C程序员认为这是错误的写法 [复制链接]

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
411 [报告]
发表于 2012-09-03 23:41 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
412 [报告]
发表于 2012-09-03 23:41 |只看该作者
回复 403# pmerofc


    这么说:
    1. void*与char*可互换 (6.2.5.26)
    2. object指针可转换为void*再转换回来 (6.3.2.3.1) --> 可以转换为 char* 再换回来
    3. object的value可以拷贝至unsigned char[n] (6.2.6.1.4) --> 可以用 unsigned char* 遍历此value
    4. 数组内元素连续(contiguously, 假如这里的 contiguously allocated 意为“顺序存储”) (6.2.5.20)
        --> 4.1 a[0] 与 a[1] 相邻 --> a[0][1] 与 a[1][0] 相邻
    3+4: (unsigned char*)&b[0]+sizeof(*b) == (unsigned char*)&b[1]
        --> 3+4.1 (unsigned char*)&a[0][1]+sizeof(**a) == (unsigned char*)&a[1][0]
           --> +2 (typeof(*a))((unsigned char*)&a[0][1]+sizeof(**a)) == (typeof(*a))((unsigned char*)&a[1][0])

    end.

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
413 [报告]
发表于 2012-09-03 23:44 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
414 [报告]
发表于 2012-09-03 23:45 |只看该作者
本帖最后由 Ager 于 2012-09-03 23:46 编辑
pmerofc 发表于 2012-09-03 23:41
难的是真弄出点事情来(据说是真有安全隐患)
真的让错“表现”出来
很多人一下子就接受了


这种纠结,属于关于“元叙事”的困惑。

你要“真弄出点事情来”,那你就得去精心构造。

构造之前,必须对“元叙事”进行解构,用哲学的话说:你在干一件后现代主义的活儿。

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
415 [报告]
发表于 2012-09-03 23:47 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
416 [报告]
发表于 2012-09-03 23:50 |只看该作者
回复 413# pmerofc


    我的意思是,标准并没有把不同类型的指针完全隔离(例: 6.2.6.1.4),桥梁就是通用指针(void*, 即char*)

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
417 [报告]
发表于 2012-09-03 23:53 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
418 [报告]
发表于 2012-09-04 00:03 |只看该作者
回复 417# pmerofc


    但 unsigned char 有. void* <-6.2.6.1.4-> char* <-6.2.5.6+6.3.2.3.7-> unsigned char*

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
419 [报告]
发表于 2012-09-04 01:15 |只看该作者
OwnWaterloo 发表于 2012-05-12 16:14
单看T a[M][N];确实有这种可能性:
T* p = &a[0][0];
通过 p (类型为T*)的计算只能保证正确 &a[0][0] 到 &a[0][N] 之间的元素,对超过&a[0][N]的部分(并不一定恰好在&a[0][N],也许在之后的某个点)可能会发生回绕。于是结果就乱七八糟。
而T* q = &a[1][0]; 通过q,才能保证正确访问 &a[1][0] 到 &a[1][N]之间的元素。


但结合malloc(还有union等东西),如果编译器敢这么设计T* p的指针格式,那么:
T* p = (T*)malloc(M * N * sizeof(T) ); // 或者按你在56楼的写法, p = (T*)malloc(sizeof(T[N*M])) 或calloc
p 也无法访问被分配出来的所有空间。



我不知道怎么准确的描述……总之,可能存在单个object大小(也许是一个数组object)远小于地址空间的情况。
也存在字长不能寻址整个地址空间,于是编译器只能用两个机器字来拼出一个指针。
在这种情况下,对指针运算,编译器为了效率,只改这两个机器字中的一个而忽略另一个也是合乎C规范的。这种实现的可能性也是存在的。


但这单个object,可以被解释为任意类型(包括某种结构体,包括解释为一维/多维数组对象)。
编译器为了效率,在节省了一个机器字改动的情况下,应该会尽量宽松,尽量让另一个能寻址这单个object的任意位置。
而不会更严格,不会为了检查出更多不合乎C规范的错误,做出更多限制。


这个,要关注一下。

:)

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
420 [报告]
发表于 2012-09-04 17:00 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP