size_t ptrdiff_t和地址空间

时间:2018-08-20 16:21:52

标签: c++ pointers size memory-address

在我的系统上, data = sorted(d.items(), key=lambda x: x[1]['weight'], reverse=True) {% for key,var in d %} <table> <tr> <td>{{ key }}</td> <td>{{ var['weight'] }}</td> </tr> </table> {% endfor %} ptrdiff_t都是 64位

我想澄清两件事:

  • 我相信由于地址空间的限制,没有任何一个数组可以和size_t一样大。这是真的吗?

  • 如果是,那么是否可以保证size_t能够保留最大数组中任何指针相减的结果?

3 个答案:

答案 0 :(得分:4)

不,没有这样的保证。例如,请参见此处:https://en.cppreference.com/w/cpp/types/ptrdiff_t

  

如果数组太大(大于PTRDIFF_MAX元素,但小于PTRDIFF_MAX元素)   大于SIZE_MAX字节),则两个指针之间的差异可能不会   可表示为std :: ptrdiff_t,减去两个这样的结果   指针是未定义的。

答案 1 :(得分:3)

大多数实现都是人为地限制最大数组大小,以确保指向同一数组的两个指针之间的差异适合ptrdiff_t。因此,在您的平台上,最大可能的数组大小很有可能约为SIZE_MAX / 2(尝试一下)。这不是“地址空间限制”,它只是实现内部执行的限制。在此限制下,合法指针减法(“ legal” =两个指针进入同一数组)不会溢出。

尽管语言规范不要求这样做。不需要实现以这种方式限制其数组大小,这意味着语言规范允许看似合法的指针减法溢出并产生未定义的行为。但是大多数实现都倾向于通过限制其数组大小来对此进行防御。

有关更多详细信息,请参见此处的“三个选项”:Why is the maximum size of an array "too large"?

答案 2 :(得分:3)

来自[support.types.layout] / 3

  

类型size_t是实现定义的无符号整数类型,其大小足以容纳任何对象的字节大小。

因此,可以保证size_t可以容纳您可以拥有的最大数组的大小。

不幸的是,

ptrdiff_t并不能保证如此。来自[support.types.layout] / 2

  

类型ptrdiff_t是实现定义的带符号整数类型,可以在数组对象中保存两个下标的差,如8.7中所述。

哪个还可以,但是我们有[expr.add] / 5

  

当减去指向同一数组对象元素的两个指针时,结果的类型为实现定义的带符号整数类型;此类型应与在标头(21.2)中定义为std :: ptrdiff_t的类型相同。如果表达式P和Q分别指向同一数组对象x的元素x [i]和x [j],则表达式P-Q的值为i-j;否则,行为是不确定的。 [注意:如果值i − j不在std :: ptrdiff_t类型的可表示值的范围内,则行为是不确定的。 —尾注]

其中指出ptrdiff_t可能不够大。