免费注册 查看新帖 |

Chinaunix

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

[C] 请教一个基础问题——数组名减1是否可以 [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
171 [报告]
发表于 2009-12-19 18:26 |只看该作者

回复 #170 mik 的帖子

我想,你的意思是不是:
无论指针如何表现, 在解引用之前, 一定会将指针的表示转换成一个数 —— 这个数能够标识地址空间中的一个unique 单元, 用这个数去访问这个段元。

这个说法我是赞同的, 而且在这帖子里面我好像也提到过, 不过刚才翻了很久没翻到, 确实太长…… 或许是在别的贴里提到过。


但是,"指针的representation可以map到一个unique的number",并不等于这不等于指针的representation就是一个number。
你认为呢?


或者这么说, 指针能否当作一个数, 是看问题的层次不同:
1. 如果在解引用那一刻, 那应该是存在一个数。
2. 如果在解引用之前, 并不一定是一个数。

但对lz的case, 如果, 能够保证指针的 ++, -- 一定能正确的反应到map后的那个数, 那么可以在1的层次上理解这个问题。
但是, 有这样的保证吗?
如果没有这个保证, 就只能将其按层次2来理解, 不要将指针理解为1个数, 而就是理解为一个抽象的事物 —— 指针 —— 以及该抽象事物支持的操作。


你认为呢?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
172 [报告]
发表于 2009-12-19 18:27 |只看该作者

回复 #170 mik 的帖子

那些话能说明确实存在这种情况(如果作者不是乱说的) :
指针的representation,不是一个数。

不过这不是重点。 重点我在ls有说明。

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

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
174 [报告]
发表于 2009-12-19 19:02 |只看该作者

回复 #170 mik 的帖子

具体点的说, 将106的例子更详细的描述一下 :

假设有这样一种机器:
int 是16位, size_t 是16位, 最大的对象大小是 2^16-1。
指针的representation是2个int: (segment, offset)。
或者说, 是一个32位的long —— 是1个数,还是2个数,这都没有关系,不是重点。


当指针被解引用时,需要将representation以某种映射方式转换到一个地址。 根据指针描述的地址空间不同, 映射方式也可以不同。
比如 segment × 16 + offset ?
或者 segment << 16 + offset 。

但是这些映射方式, 都能够将指针的representation, 映射到一个unique的数 —— 地址 —— 用于访问该单元。

这点我是赞同的。


但是, 指针的 ++, --, 并不能保证能够正确反应到它被映射后的数上。举例:
还是上面那种机器,假设指针的 ++ , --是这样实现的:只会改变representation (segment, offset) 中的 offset, 不会引起segment的变化。
这是合理的 —— 对数组 a[ n ], 标准只要求实现能够保证: a +0 到 a + n 不产生溢出。
只变化offset, 并且按标准所说的行事, 就能够满足这种保证 —— 只要指针在a+0到a+n之间, 指针被映射后的数, 也拥有正确的地址。

但是, 在这种机器以及这种指针的实现方式下, 对指针的所有 ++, -- 操作就不能保证全都能被正确反映到指针被映射后的数上了。 除非严格按照标准的要求, 让指针只在 a+0到a+n 之间移动。

比如有一个数组a,大小为326, 起始地址由指针 (1212,0) 标识。
a + 0 就是(1212,0), a +326就是 (1212,326)。 被映射后, 都是合法的地址。
但是a -1? 有可能就是 (1212, 2^16-1) , 映射后的地址可能依然是合法的, 但对lz的case : 逆向遍历数组, 就会形成死循环。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
175 [报告]
发表于 2009-12-19 19:09 |只看该作者

回复 #174 OwnWaterloo 的帖子

补充一下, 上面末尾中, 就出现了一种情况: 指针 -- 并不能引起指针被映射后的数 -- , 而是引起那个数增加。
指针 -- 后, 指向的并不是前一个单元, 而是之后。

但上面的实现依然是合理的。 因为它满足标准对实现的要求。
所以,可以将指针理解为一个数, 用于标识唯一的单元。 但这个数上的操作,和普通的数有区别,指针是一种受限制的数。
—— 与其这样理解, 还不如就将指针理解为指针, 一种抽象事物, 它可以标识一个唯一的单元, 它可以执行++, --, 但一定要在a+0, a+n之间才有意义。

论坛徽章:
0
176 [报告]
发表于 2009-12-19 19:35 |只看该作者
没有意义

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

论坛徽章:
1
狮子座
日期:2013-12-16 16:09:24
178 [报告]
发表于 2009-12-20 00:20 |只看该作者
看了给出的标准之后才知道
      1 #include <stdio.h>
      2 int main(){
      3         int a[]={1,2,3};
      4         int * p=a+3;
      5         do{
      6                 p--;
      7                 printf ("%d",*p);
      8         }while(p>a);
      9         return 0;
     10 }

这样写是安全的,第四行改为p+4或者改成for写都是不安全的。以后要注意!!!
纵观几个大牛的帖子,有一种感觉,这个标准对很多人都“没有问题”,就是对lz有问题

理论派:
不知道为何标准没有考虑反向遍历的需求,制定者有问题,应该跟新标准!

实践派:
这么多年程序搞下来了,没听说过有人强调标准里这条的重要性。检验好程序的标准时什么?遵守理论?实际运行的正确性?反过来讲,遵守了这个标准的人,能写出比忽视这个标准的人更少bug的程序么?!

论坛徽章:
0
179 [报告]
发表于 2009-12-20 00:28 |只看该作者

回复 #171 OwnWaterloo 的帖子

你在 171、172、174、175 楼的回复都是基于你这种先入为主的观点,

你认为:指针是以 segment + offset 这种形式表现。

----------------------------------------------------------------------------------------------

我在 166 楼回复中的质疑只是:你提出的这种 “指针是 segment + offset 这种形式"

我并不是质疑 “对数组变量进行 -- 操作是未定义行为”,我没读过 C 标准,并不了解 C 标准是怎样规定的。


SO:

1、 你提出指针是: segment + offset ,有没有实质的理据去支持你的观点?

    因为,你是提出这种观点去反驳别人。

    至于引用的那段话就算了,对那段话其深刻含义每个人理解可能不同。



2、 不是每种平台都有段式的内存管理,那么显然,在那些平台上不可能有 segment + offset 指针。

    你不会认为,在 c 语言层面上:对于某些平台使用 segment + offset ,而某些平台不使用 segment +offset 表示指针吧?



3、 就拿 x86 平台来说,也不可能是 segment + offset 形式的指针。

    我在 166 楼的回复就说:segment 是硬件层面上的内存管理措施,并不是 c 语言层面上的产物。

    c 只管对于指针值进行相应的操作,至于这个指针值如何被 map 到唯一的地方,那不是 c 语言的职责。

    那是系统程序的职责。c 语言层上没职责那改变 segment 值。


    在 x86 16 位平台上,segmentffset 这种内存地址形式,那是汇编语言的表现形式。


    即使在 32 位的段式管理中,就算你设定 segment base 不是 0,segment limit 不是 4G,

    如果 data segment limit 设为 512M,c 的指针还是 int 值。还是按照它的指针运算规则进行 dereference

     因为,C 并不知道 OS 的某个 data segment limit 设为 512M

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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP