自定义的带陷阱表示的无符号短整型的大小是多少?

问题描述 投票:0回答:3

以下C标准的所有章节号都来自这个特定的C11草案版本

段。 C11 第 3.19.4 节第 1 条规定:

陷阱表示

不需要表示对象类型值的对象表示

段。 C11 第 6.2.6.2 节第 1 条规定:

对于unsigned char以外的无符号整数类型,对象的位 表示应分为两组:值位和填充位(需要 不是后者中的任何一个)。 ...

段。 C11 第 6.5.3.4 节第 2 条规定:

sizeof 运算符产生其操作数的大小(以字节为单位),这可能是一个 表达式或类型的括号名称。大小由类型决定 操作数

假设,假设我设计了一个 CPU 架构(浪费地)使用三个字节(24 位)来存储

unsigned short
。这个浪费
unsigned short
的范围还是[0, 65535]。它的最后两个字节是一个普通的
uint16_t
,第一个字节是为所有可能的陷阱表示保留的。

为了简单起见,假设

unsigned short
只有在第一个字节是
0000 0000
时才有效;如果第一个字节不是
unsigned short
.
,则 
0000 0000

未初始化(因此是陷阱表示)

问题是,对于我浪费的一个变量

unsigned short

unsigned short a = 123;

sizeof
的预期结果是什么?:

sizeof a;

更重要的是,应该使用C标准的哪一部分的哪一段来支持预期的结果?

编辑1: 所有对

uint16_t
的引用都更改为
unsigned short
,因为一些用户指出
uint16_t
不能有填充位。

c language-lawyer sizeof
3个回答
0
投票

C标准对此有明确规定;问题中唯一不清楚的地方,特别是它是使用 C 标准意义上的“字节”(至少八位的单位,用作 C 对象模型的构建块)还是八位意义上的“字节” .

C标准说除了位域之外的所有对象都是由字节组成的,一个

char
就是一个字节,而且至少要有八位。如果一个字节是八位,那么一个 24 位对象的大小必须是三个字节。如果一个字节可以大于八位,则允许 24 位对象的可能性是 12 位和 24 位,使得 24 位对象的大小分别为两个字节和一个字节。


0
投票

byte的C语言定义,C17 3.6:

字节
大到足以容纳基本字符的任何成员的数据存储的可寻址单元 一套执行环境

一个字节有多少位,C没有定义,只是必须至少8. C17 5.2.4.2.1:

  • 不是位域的最小对象的位数(字节)
    CHAR_BIT   8

sizeof
保证返回操作数使用的字节数,所以如果您的
unsigned short
是 3 个字节,它将返回 3。 C17 6.5.3.4

sizeof
运算符产生其操作数的大小(以字节为单位)

因此

sizeof
的预期结果是 3。该数据类型中的位数将为
3 * CHAR_BIT
sizeof
返回对象大小,它可能大于对象的一部分的值,如使用填充的任何
struct
所见。

值得注意的是,类型的整数值范围不一定对应于字节大小。只要看看任何带符号的类型,取值范围(至少)比该类型使用的总位数少 1 位。


-1
投票

sizeof 运算符的结果不依赖于存储在对象中的值。

正如你自己写的

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

所以根据你的描述

假设,假设我设计了一个 CPU 架构 (浪费)使用三个字节

sizeof 运算符将返回 3,尽管类型名称会使用户感到困惑。

更真实的情况是结构。它们的数据成员之间可以有许多填充,并且考虑这些填充以确定必须为结构类型的对象分配多少内存。例如,结构类型的数据成员可以是

uint16_t
。因此,为了确定结构的大小,编译器需要知道其数据成员实际占用了多少内存。

还要考虑指针运算。如果你有一个像

这样的数组
uint16_t a[2];

那么表达式

a + 1
必须指向数组的第二个元素。表达式的计算方式类似于
( char * )a + sizeof( uint16_t )
。如果
sizeof( uint16_t )
不等于3,你会得到一个不正确的值。

© www.soinside.com 2019 - 2024. All rights reserved.