什么决定 sizeof(int)

电器工程 微控制器 C 大气压 嵌入式
2022-01-31 23:39:09

关于标准数据类型,ATmega 控制器中整数的大小是多少?什么决定了大小,仅仅是编译器吗?还是在控制器本身的硬件设计中,因此所有 ATmega 编译器都必须遵守该大小?如果它在硬件中,为什么在 PC 中你可以有两个不同的编译器为 sizeof(int) 提供不同的结果,即使它们在同一个处理器上运行?

3个回答

int是C型。ATMega 对此一无所知,它们只能使用 8 位字节(因为它们具有 8 位 AVR CPU)。

编译器将int类型上的任何操作转换为在 CPU 架构所需的大小级别执行该操作所需的等效操作 - 对于 AVR,它被转换为在字节级别执行操作,对于 16 位 CPU,它将在16位级别等

类型在编译avr-gccint中被简单地定义为2 字节整数它基于平台而变化的事实意味着您最好使用<stdint.h>类型,例如uint16_t如果您想确定需要可移植的代码大小。有符号和无符号的所有标准整数大小 (8,16,32,64) 的类型定义。

所谓的_fast类型还有其他定义,它们保证至少是所需的大小,但会根据平台生成最快的代码,例如 32 位处理器倾向于比 8 位数字更有效地对 32 位数字执行操作,所以 uint_fast8_t在 32 位平台上将是 32 位整数(它至少为 8 位,但处理速度更快)。

sizeof()指令在编译时执行,并转换为常量,处理器不执行。avr-gcc知道它定义了多大的intas,所以它知道用什么常量替换sizeof()调用。

int, short int,等的大小long int由编写编译器的人决定。C 的规则是short int<= int<= long int,但这为编译器编写者留下了足够的空间。

编译器编写者分析处理器的功能并尝试为该 CPU 做出明智的选择。他们经常给出命令行标志来强制int一个特定的大小,以便更容易跨处理器移植代码。

编译器生成不同的代码序列来处理不同大小的int;CPU 由代码驱动,因此实现了编译器输出定义的大小。

Atmega 使用 AVR 的 CPU 架构。它一次主要处理 8 位数据。所以编译器必须生成代码来实现多字节算术。

大多数 ATmege 的底层地址空间是 16 位的,因此拥有可以访问所有这些的算术非常方便。因此,默认情况下,anint为 16 位。在具有分段内存的 x86 的“过去”中,地址可以是 16 位或 32 位,并且编译器被指示为特定“模型”生成 cde,编译器通常生成的代码大小int可以保持大小该“内存模型”的指针。

如果您为同一处理器使用编译器,能够为两个(或更多)不同大小的 int(int、 not short intlong int、 just int)生成代码,那么这正是它响应适当标志(或 pragma 的)。

编译器“知道”int它生成代码的大小,因此 asizeof(int)将在编译时由编译器替换为正确的值。

标准 C 数据类型的大小由编译器实现决定。根据标准,int 必须能够包含 -32767 到 32767(16 位)范围内的值,但可能更大。int 的大小通常是 CPU 最自然的值——字大小或 CPU 寄存器的大小。

唯一确定的方法是查阅编译器手册或编写测试代码。拥有一份嵌入式编译器手册的副本是个好主意,因为对齐和数据存储的细节在嵌入式编程中可能更重要。编译器扩展(例如中断支持)也更重要。

如果你有一个 C99 兼容的编译器,使用定义的 uintX_t 类型来获得你想要的大小会更容易。

作为参考,这里是取自 C99 标准第 5.2.4.2.1 节的其他数据类型的最小大小。请注意,不需要二进制补码算术,尽管我不知道任何人的补码或符号幅度机器。

char(字节大小): sizeof(char) 始终等于 1。有符号字符必须保存在 -127 到 127 范围内的值。无符号字符必须保存在 0 到 255 范围内的值。该标准还指定了字符中的最小位数字符/字节,即 8。

短: -32767 到 32767 表示有符号,0 到 65535 表示无符号。相当于 16 位。

int:与short相同。

long: -2147483647 到 2147483647 为有符号,0 到 4294967295 为无符号。相当于 32 位。

long long: -9223372036854775807 到 9223372036854775807 用于签名,0 到 18446744073709551615 用于未签名。相当于 64 位。

指针:实现定义。该标准允许指向不同数据类型的指针有不同的“表示和对齐要求”,但我在实践中从未见过。