引用此博文:
http://www.codesynthesis.com/~boris/blog/2008/10/13/writing-64-bit-safe-code/
这是有效的,因为有效的内存索引只能在[0,~size_t(0)-1]范围内.例如,在std :: string中使用相同的方法.
那么为什么~size_t(0)(这通常应该0xFFFFFFFF在32位系统中相等)不是有效的数组索引?我假设如果你有32位你应该能够引用整个范围[0,0xFFFFFFFF],不是吗?
Die*_*Epp 47
重要说明:术语"记忆索引"含糊不清且令人困惑.链接文章严格指代数组索引,而不是内存中的地址.
size_t无法表示所有内存地址完全有效,这就是我们intptr_t在C99中使用类型的原因.当然,这不适用于您的工作站,它无疑具有简单的Von Neumann类型架构. (此问题已被编辑以删除对"内存索引"的引用.)
C标准保证size_t可以容纳任何数组的大小.但是,对于任何数组a[N],标准保证a + N必须是有效指针并且比较不等于任何指向元素的指针a.
因此,size_t必须能够表示至少一个大于任何可能的数组索引的值.由于~(size_t)0保证是最大值size_t,因此它是数组索引的标记的一个很好的选择.
讨论:
为什么~(size_t)0保证最大值? 因为标准明确地这样说:来自§6.5.3.3:"如果提升类型是无符号类型,则表达式~E等于该类型中可表示的最大值减去E." 请注意,(size_t)-1保证也是从有符号类型到无符号类型的转换规则的最大值.不幸的是,SIZE_MAX在您的平台上找到定义并不总是那么容易,所以(size_t)-1并且~(size_t)0是首选.(请注意,如果int可以表示,则不再适用SIZE_MAX......但这不会在实际系统中发生.)
索引从0到0的数组大小是多少? 根据C标准,通过本文顶部概述的参数,这样的数组不可能存在.
如果你malloc(-1),生成的内存区域必须从0开始.(FALSE)标准允许有很多非常奇怪的情况,但实际上并没有遇到.例如,想象一个系统在哪里(uintptr_t)-1 > (size_t)-1.C标准完全按照它的方式进行措辞,因为它不仅可以在您的PC上运行,而且可以在具有哈佛架构的奇怪的小型DSP上运行,并且可以在具有拜占庭内存分段方案的古老系统上运行.还有一些具有历史意义的系统,其中NULL指针与0没有相同的表示.
App*_*eue 14
直觉是这样的:
x = malloc(~size_t(0)); // the most you can allocate
x[~size_t(0) -1]; // the highest valid index
Run Code Online (Sandbox Code Playgroud)
AnT*_*AnT 13
好吧,正如@Apprentice Queue在他的回答中正确指出的那样,因为C或C++程序中最大的连续对象的大小受限于SIZE_MAX(相同(size_t) -1,相同~size_t(0)),所以最大索引需要索引该对象的字节是SIZE_MAX - 1.但与此同时,正如@Dietrich Epp在他的回答中正确指出的那样,C和C++允许地址算法超出数组末尾的一个元素,这使得SIZE_MAX一个有效的索引,如果不是为了访问数组元素,那么至少对于指针算术.因此,正式来说SIZE_MAX,它是一个有效的索引,即使它不能代表数组的现有元素.
然而,使用size_t允许"索引整个内存"的类型的整个想法仅在某个特定平台的范围内有效,其中size_t确实恰好足以进行内存索引("平面内存"平台,如Win32,Win64) ,Linux属于这一类).实际上,从一般的角度来看,类型size_t不足以进行内存索引.size_t只保证类型足以在C或C++程序中索引单个连续对象中的字节.C和C++都不保证支持覆盖整个地址空间的连续对象.换句话说,类型size_t保证足以索引C/C++程序中任何显式声明的数组对象,但通常不能保证足以计算链表中的节点.然而,假设在某个特定平台上的范围size_t确实涵盖了整个内存,(size_t) -1看起来像是"保留"值的一个很好的选择,因为这个索引只能代表覆盖该字节数组的字节数组中的最后一个字节.整个地址空间.显然,实际索引中没有人会在实践中需要这个索引.
然而,如果你真的对可以索引整个内存的正式合适类型感兴趣(并且因此能够在任何内存容器中存储元素的数量),那就uintptr_t不是size_t.该博客文章的作者似乎确实理解这里的一般问题,因为他指出这size_t不适合索引文件(即用于存储文件大小或偏移).但是,仍然很高兴注意到几乎相同的原因类型size_t也不适合索引内存.类型size_t与RAM或进程地址空间并不真正相关,这与作者在其博客文章中声称的相反.类型uintptr_t与进程地址空间有关,但不是size_t.size_t在他提到的平台上足够的事实只不过是那些平台的特定属性.
| 归档时间: |
|
| 查看次数: |
3266 次 |
| 最近记录: |