为什么定义了sizeof实现的结果

Why is the result of sizeof implementation defined?

本文关键字:结果 实现 sizeof 定义 为什么      更新时间:2023-10-16

在C99中,§6.5.3.4:

2sizeof运算符产生其操作数的大小(以字节为单位),其可以是表达式或类型的带括号的名称。。。

4结果的值由实现定义,其类型(无符号整数类型)是在<stddef.h>中定义的size_t(以及其他标头)。

在C++14中,§5.3.3:

1sizeof运算符产生对象中的字节数其操作数的表示。。。sizeof的结果应用于任何另一个基本类型(3.9.1)是实现定义的。

唯一的保证值是sizeof(char)sizeof(unsigned char)sizeof(signed char),它们是一个。

然而,"对象表示中的字节数"对我来说似乎是铁一般的。例如,在C99§6.2.6.1中:

4存储在任何其他对象类型的非位字段对象中的值由n×CHAR_BIT位组成,其中n是对象的大小以字节为单位。。。

那么,如果它看起来定义得很好,为什么要定义它的实现呢?


你们中的许多人似乎误解了我的问题。我从未声称:

A) 类型的大小在所有系统上都有定义或相同,

B) 实现定义意味着它可以返回"随机值">

我得到的是n * CHAR_BITS是一个固定的公式。公式本身不能在不同的实现之间更改。是的,int可以是4个字节,也可以是8个字节。我明白了。但是在所有实现之间,该值必须为n * CHAR_BITS

sizeof的结果是实现定义的,因为各种基本类型的大小都是实现定义。我们对C++中类型大小的唯一保证是

sizeof(char) = 1 and sizeof(char) <= sizeof(short) <= sizeof(int) <= 
sizeof(long) <= sizeof(long long)

每种类型都有一个最小值,它必须支持C11[附件E(资料性)实施限制]/1

[…]显示的最小幅度应替换为具有相同符号的实施定义幅度。[…]

#define CHAR_BIT    8
#define CHAR_MAX    UCHAR_MAX or SCHAR_MAX
#define CHAR_MIN    0 or SCHAR_MIN
#define INT_MAX     +32767
#define INT_MIN     -32767
#define LONG_MAX    +2147483647
#define LONG_MIN    -2147483647
#define LLONG_MAX   +9223372036854775807
#define LLONG_MIN   -9223372036854775807
#define MB_LEN_MAX  1
#define SCHAR_MAX   +127
#define SCHAR_MIN   -127
#define SHRT_MAX    +32767
#define SHRT_MIN    -32767
#define UCHAR_MAX   255
#define USHRT_MAX   65535
#define UINT_MAX    65535
#define ULONG_MAX   4294967295
#define ULLONG_MAX  18446744073709551615

因此,根据标准,int必须能够存储一个可以存储在16位中的数字,但它可以更大,在当今的大多数系统中,它是32位。

我得到的是n * CHAR_BITS是一个固定的公式。公式本身不能在不同的实现之间更改。是的,int可以是4个字节,也可以是8个字节。我明白了。但在所有实现之间,值必须为n * CHAR_BITS

您是正确的,但n根据C99§6.2.6.1定义为

其中n是该类型的对象的大小

emphasis mine

因此,公式可以是固定的,但n不是固定的,并且在同一系统上的不同实现可以使用不同的n值。

sizeof的结果未定义实现。标准没有这么说;上面写着:

结果的值是实现定义的,[…]

这在语义上是不同的。sizeof的结果是明确的:

[…]其操作数的大小(以字节为单位)[…]

此上下文中字节的位宽和非char类型中的字节数都是实现定义的。

因为基本类型的大小是根据效率来定义的,而不是根据确切的位数来定义的。"int"必须是CPU能够有效操作的东西。对于大多数现代系统来说,这个数量是32位(或64位)。对于较旧的系统,它通常是16位。然而,如果存在35位的CPU,那么在这样的系统上的int将是35位。换句话说,C++不会应用惩罚来强制执行CPU可能根本不支持的位宽。

当然,有人可能会说,基本类型的奇异位宽的概念已经被历史所取代。我想不出有哪个现代CPU不支持8、16和32位的标准集(不同意这一说法,但至少要举个例子!),64位也很常见(如果硬件支持不可用,在软件中支持也没什么大不了的)。

可以说,C++语言已经不再使用可变位数的char;据我所知,u8"…"转换为char*,但unicode规范要求u8以8位编码。

如果8位的char的大小为1,那么32位的int的大小为4。如果16位的char的大小为1,那么32位的int的大小仅为2。如果这样的大小恰好是它们各自硬件的好选择,那么这两种情况在C++中都同样有效。

填充位是"未指定的",而不是"实现定义的"。

错误。非常非常错误。填充字节的未指定。这里的意图是这些比特的值可以表示陷阱值,但不一定。

标准告诉sizeof返回bytes * CHAR_BITS,但不指定大小(除了exact-width类型)。一个类型占用的字节数是由实现定义的,因此sizeof也必须是。

定义的实现描述为:

未指定的值,其中每个实现记录如何选择被制成

当您在以下示例中声明一个新变量时:

size_t a;

它将等于:

unsigned short int a; // unsigned short a

在32位计算机上,整数(int)的大小为4字节。短int的大小为2字节。

在C编程语言中,"size_t"是"sizeof()"运算符的返回类型。当你使用"sizeof()"运算符时,他会给你对象的大小。"sizeof()"的参数必须是l-value类型。元素(对象)的大小不能是负数,并且必须是整数。