为什么数组的最大大小“太大"? [英] Why is the maximum size of an array "too large"?

查看:27
本文介绍了为什么数组的最大大小“太大"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我和这个答案的印象相同,总是保证size_t按照标准,足够大以容纳给定系统的最大可能类型.

但是,此代码无法在 gcc/Mingw 上编译:

#include #include typedef uint8_t array_t [SIZE_MAX];

<块引用>

错误:数组'array_t'的大小太大

我是否误解了此处的标准?对于给定的实现,size_t 是否允许太大?或者这是 Mingw 的另一个错误?

<小时>

进一步研究表明

typedef uint8_t array_t [SIZE_MAX/2];//编译typedef uint8_t array_t [SIZE_MAX/2+1];//不编译

恰好与

相同

#include typedef uint8_t array_t [LLONG_MAX];//编译typedef uint8_t array_t [LLONG_MAX+(size_t)1];//不编译

所以我现在倾向于相信这是 Mingw 中的一个错误,因为根据有符号整数类型设置允许的最大大小没有任何意义.

解决方案

SIZE_MAX/2 的限制来自于你的实现中 size_t 和 ptrdiff_t 的定义,它们选择类型 ptrdiff_t 和 size_t 具有相同的宽度.

C 标准要求1 类型 size_t 是无符号的,类型 ptrdiff_t 是有符号的.

两个指针不同的结果,总是2具有类型ptrdiff_t.这意味着,在您的实现中,对象的大小必须限制为PTRDIFF_MAX,否则无法在类型 ptrdiff_t 中表示两个指针的有效差异,从而导致未定义的行为.

因此值 SIZE_MAX/2 等于值 PTRDIFF_MAX.如果实现选择将最大对象大小设为 SIZE_MAX,则必须增加 ptrdiff_t 类型的宽度.但是将对象的最大大小限制为 SIZE_MAX/2 要容易得多,那么就是让 ptrdiff_t 类型的范围大于或等于 size_t 类型的范围.

Standard 提供关于该主题的这些3 评论4.

<小时>

(引用自 ISO/IEC 9899:201x)

1(7.19 通用定义 2)
类型是
ptrdiff_t
这是两个指针相减结果的有符号整数类型;
尺寸_t
这是sizeof运算符结果的无符号整数类型;

2(6.5.6 加法运算符 9)
当两个指针相减时,都指向同一个数组对象的元素,或超过数组对象的最后一个元素;结果是不同的两个数组元素的下标.结果的大小是实现定义的,它的类型(有符号整数类型)是在头文件中定义的 ptrdiff_t .如果结果在该类型的对象中无法表示,则行为未定义.

3(K.3.4 整数类型 3)
非常大的对象大小通常是计算对象大小的标志不正确.例如,当负数显示为非常大的正数时转换为无符号类型,如 size_t.此外,某些实现不支持与 size_t 类型可以表示的最大值一样大的对象.

4(K.3.4 整数类型 4)
由于这些原因,有时限制要检测的对象大小范围是有益的编程错误.对于针对具有大地址空间的机器的实现,建议将 RSIZE_MAX 定义为最大的大小中的较小者对象支持或 (SIZE_MAX >> 1),即使此限制小于一些合法但非常大的对象.针对小型机器的实现地址空间可能希望将 RSIZE_MAX 定义为 SIZE_MAX,这意味着不存在被视为违反运行时约束的对象大小.

I'm under the same impression as this answer, that size_t is always guaranteed by the standard to be large enough to hold the largest possible type of a given system.

However, this code fails to compile on gcc/Mingw:

#include <stdint.h>
#include <stddef.h>

typedef uint8_t array_t [SIZE_MAX];

error: size of array 'array_t' is too large

Am I misunderstanding something in the standard here? Is size_t allowed to be too large for a given implementation? Or is this another bug in Mingw?


EDIT: further research shows that

typedef uint8_t array_t [SIZE_MAX/2];   // does compile
typedef uint8_t array_t [SIZE_MAX/2+1]; // does not compile

Which happens to be the same as

#include <limits.h>

typedef uint8_t array_t [LLONG_MAX];           // does compile
typedef uint8_t array_t [LLONG_MAX+(size_t)1]; // does not compile

So I'm now inclined to believe that this is a bug in Mingw, because setting the maximum allowed size based on a signed integer type doesn't make any sense.

解决方案

The limit SIZE_MAX / 2 comes from the definitions of size_t and ptrdiff_t on your implementation, which choose that the types ptrdiff_t and size_t have the same width.

C Standard mandates1 that type size_t is unsigned and type ptrdiff_t is signed.

The result of difference between two pointers, will always2 have the type ptrdiff_t. This means that, on your implementation, the size of the object must be limited to PTRDIFF_MAX, otherwise a valid difference of two pointers could not be represented in type ptrdiff_t, leading to undefined behavior.

Thus the value SIZE_MAX / 2 equals the value PTRDIFF_MAX. If the implementation choose to have the maximum object size be SIZE_MAX, then the width of the type ptrdiff_t would have to be increased. But it is much easier to limit the maximum size of the object to SIZE_MAX / 2, then it is to have the type ptrdiff_t have a greater or equal positive range than that of type size_t.

Standard offers these3 comments4 on the topic.


(Quoted from ISO/IEC 9899:201x)

1 (7.19 Common definitions 2)
The types are
ptrdiff_t
which is the signed integer type of the result of subtracting two pointers;
size_t
which is the unsigned integer type of the result of the sizeof operator;

2 (6.5.6 Additive operators 9)
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the header. If the result is not representable in an object of that type, the behavior is undefined.

3 (K.3.4 Integer types 3)
Extremely large object sizes are frequently a sign that an object’s size was calculated incorrectly. For example, negative numbers appear as very large positive numbers when converted to an unsigned type like size_t. Also, some implementations do not support objects as large as the maximum value that can be represented by type size_t.

4 (K.3.4 Integer types 4)
For those reasons, it is sometimes beneficial to restrict the range of object sizes to detect programming errors. For implementations targeting machines with large address spaces, it is recommended that RSIZE_MAX be defined as the smaller of the size of the largest object supported or (SIZE_MAX >> 1), even if this limit is smaller than the size of some legitimate, but very large, objects. Implementations targeting machines with small address spaces may wish to define RSIZE_MAX as SIZE_MAX, which means that there is no object size that is considered a runtime-constraint violation.

这篇关于为什么数组的最大大小“太大"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆