免费注册 查看新帖 |

Chinaunix

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

地址相减的结果? [复制链接]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
21 [报告]
发表于 2007-05-12 14:08 |只看该作者
原帖由 whyglinux 于 2006-8-17 19:34 发表
其结果是无定义的。其原因:
  • 0x509如果被转换为int指针值的话其地址显然是不对齐的,因此这种转换行为是无定义的。
  • 两个指针的相减运算只有在指针都指向同一个数组对象(至多超过结尾的一个元 ...

正解。

再引用下 comp.lang.c 的 FAQ 中一些类似问题吧:
Question 4.14
Q: How are integers converted to and from pointers? Can I temporarily stuff an integer into a pointer, or vice versa?

A: Once upon a time, it was guaranteed that a pointer could be converted to an integer (though one never knew whether an int or a long might be required), and that an integer could be converted to a pointer, and that a pointer remained unchanged when converted to a (large enough) integer and back again, and that the conversions (and any mapping) were intended to be ``unsurprising to those who know the addressing structure of the machine.'' In other words, there is some precedent and support for integer/pointer conversions, but they have always been machine dependent, and hence nonportable. Explicit casts have always been required (though early compilers rarely complained if you left them out).

The ANSI/ISO C Standard, in order to ensure that C is widely implementable, has weakened those earlier guarantees. Pointer-to-integer and integer-to-pointer conversions are implementation-defined (see question 11.33), and there is no longer any guarantee that pointers can be converted to integers and back, without change.

Forcing pointers into integers, or integers into pointers, has never been good practice. When you need a generic slot that can hold either kind of data, a union is a much better idea.

See also questions 4.15, 5.18, and 19.25.

References: K&R1 Sec. A14.4 p. 210
K&R2 Sec. A6.6 p. 199
ISO Sec. 6.3.4
Rationale Sec. 3.3.4
H&S Sec. 6.2.3 p. 170, Sec. 6.2.7 pp. 171-2

Question 19.25
Q: How can I access memory (a memory-mapped device, or graphics memory) located at a certain address?
How can I do PEEK and POKE in C?

A: Set a pointer, of the appropriate type, to the right number (using an explicit cast to assure the compiler that you really do intend this nonportable conversion):

        unsigned int *magicloc = (unsigned int *)0x12345678;

Then, *magicloc refers to the location you want. [footnote] If the location is a memory-mapped I/O register, you will probably also want to use the volatile qualifier: ``volatile unsigned int *magicloc''. (If you want to refer to a byte at a certain address rather than a word, use unsigned char *.)

Under MS-DOS, you may find a macro like MK_FP() handy for working with segments and offsets. As suggested by Gary Blaine, you can also declare tricky array pointers which allow you to access screen memory using array notation. For example, on an MS-DOS machine in an 80x25 text mode, given the declaration

unsigned short (far * videomem)[80] =
                (unsigned short (far *)[80])0xb8000000;

you can access the character and attribute byte at row i, column j with videomem[ i][j].

Many operating systems execute user-mode programs in a protected mode where direct access to I/O devices (or to any address outside the running process) is simply not possible. In such cases you will have to ask the operating system to carry out I/O operations for you.

See also questions 4.14 and 5.19.

References: K&R1 Sec. A14.4 p. 210
K&R2 Sec. A6.6 p. 199
ISO Sec. 6.3.4
Rationale Sec. 3.3.4
H&S Sec. 6.2.7 pp. 171-2


总之一句话,这种做法问题多多,除非你很清楚自己在做什么,否则不要这么做

论坛徽章:
0
22 [报告]
发表于 2007-05-12 18:27 |只看该作者
原帖由 蚊见蚊爱 于 2006-8-17 15:58 发表

您就别误导别人了,

结果是2
这个看类型的
((void*)pAddr1 - (void*)pAddr2)/sizeof(type)

明白否?


按标准,void 指针是不能与 void 指针相减的,此外 void 指针加减一个常数也是没有定义的。

论坛徽章:
0
23 [报告]
发表于 2007-05-12 18:40 |只看该作者
movl    $1024, -4(%ebp)
        movl    $1033, -8(%ebp)
        movl    -4(%ebp), %edx
        movl    -8(%ebp), %eax
        subl    %edx, %eax
        sarl    $2, %eax

这就是
int *p = (int *)0x400;
        int *q = (int *)0x409;
        int a = q-p;
的代码

whyglinux 说的
0x509如果被转换为int指针值的话其地址显然是不对齐的,因此这种转换行为是无定义的。

应该是运行时的无定义,如果解引用有些体系结构上是错误的。但是这段代码本身一点问题都没有,

9/4 == 2,永远成立。

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
24 [报告]
发表于 2007-05-12 18:45 |只看该作者
LZ想象力比较好
赞叹一把!
但是奇数边界指向int,这在很多机器上是不允许的,也就是说这个指针不能够拿来访问。

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
25 [报告]
发表于 2007-05-12 18:45 |只看该作者
原帖由 flw2 于 2007-5-12 18:40 发表
movl    $1024, -4(%ebp)
        movl    $1033, -8(%ebp)
        movl    -4(%ebp), %edx
        movl    -8(%ebp), %eax
        subl    %edx, %eax
        sarl    $2, %eax

这就是
int *p = (i ...

把整数强制转换成指针存在移植性问题。

论坛徽章:
0
26 [报告]
发表于 2007-05-12 18:49 |只看该作者
原帖由 tena 于 2006-8-18 10:18 发表


回复:
value=2;
地址当然是可以相减的,不管什么类型,地址说白了不就是一个整数吗,两个整数当然可以相减(用这个办法还可以直接求字符串长度)。
等于2,是因为sizeof(int)=4, 9/4=2


我上面的问题还是有问题,用9/4只是实现的问题,估计大多数实现都是这么做的,但是并不是一定的。
怎么求值是未定义的,但是如果它们的值相差是整数倍,而且必须是两个对象地址的差才肯定能保证正确,因为这样甚至都不对:

p = 0x401;
q= 0x409;
加入机器根本不能解引用pq,那么一味着编译器不会生成这种代码。也就是编译器计算p-q的真正方法在这种机器上还依赖于 sizeof int | p.

论坛徽章:
0
27 [报告]
发表于 2007-05-12 18:52 |只看该作者
如 win_hate 版主所言,本帖更为精彩。

论坛徽章:
0
28 [报告]
发表于 2007-05-12 18:52 |只看该作者
原帖由 MMMIX 于 2007-5-12 18:45 发表

把整数强制转换成指针存在移植性问题。


对,所以这个还只是讨论而已,凡是无定义的都很可能能找到一个实现或系统不同我们通常所想象的那样

论坛徽章:
0
29 [报告]
发表于 2007-05-12 18:53 |只看该作者
不过挺佩服楼主的想象力的,呵呵

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
30 [报告]
发表于 2007-05-12 19:23 |只看该作者
原帖由 flw2 于 2007-5-12 18:52 发表
对,所以这个还只是讨论而已,凡是无定义的都很可能能找到一个实现或系统不同我们通常所想象的那样

C 语言的实现实在是太多太广了,各种各样、林林总总、不一而足。C 中的许多问题,即使是一些看似比较简单的问题,要想说的准确而详尽,都不是一件简单的事情,更非三言两语所能做到。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP