是否也可以使用5字节字或其他
是的。您甚至可以通过bit fields 仅使用几位而不是整个字节/字。从技术上讲,编译器可以在任何架构上支持任何整数大小,例如 16 位计算机上的 12 位、30 位或 96 位 int。事实上,Clang 刚刚为具有任意位宽的整数提供了一个新的扩展,称为_ExtInt。另请参阅
为什么不是 40 位或其他数字?
性能会受到很多的影响。我们需要更多指令来处理非原生整数大小。如果大小小于一个字,则编译器需要发出按位指令来屏蔽剩余的位。在相反的情况下,我们需要多个指令来处理多个单词
另一个重要的事情是misalignment。当变量的地址是其大小的倍数或至少是数据总线宽度/字大小的倍数时,现代 CPU 的工作效率更高。使用奇数大小的变量很尴尬
也就是说,存在许多具有 40 位类型的 32 位架构,例如 TI C6000 或 TI C5500 DSP
long 是
[...] 和 C5500 具有 40 位 long long
C89 Support in TI Compilers
这是因为这些 DSP 有一个特殊的 40 位累加器,允许将 32 位数字相加 256 次而不会溢出。但是为什么不直接使用 64 位累加器呢?这将需要更大的 ALU,需要更多的功率并且运行速度更慢(因为更大的区域意味着硬件组件之间的距离更长,并且在大数字上运行比在较小的数字上运行慢),这在为性能而设计的 DSP 中是不可接受的(可能还有力量)
... 例如,德州仪器公司的 TMS320C6000,一个 DSP 处理器,使用 32 位表示类型int,使用 40 位表示类型long(这种选择并不少见)。那些使用 24 位来表示类型int 的处理器(通常是 DSP)通常使用 48 位来表示类型long。在 32/64 位整数类型表示不具成本效益的应用需求中,可以使用 24/48 位整数类型表示。
The New C Standard (Excerpted material): An Economic and Cultural Commentary
事实上,40 位 int 在 DSP 中很常见(其他示例为 Blackfin 和 SHARC)。 SHARC 甚至还有一个 80 位的累加器,所以你可以添加很多 64 位的值而不用担心溢出
但您不需要特殊的架构或特殊的编译器支持。如果您确实需要,您仍然可以使用 40 位变量,例如,当您使用一个巨大的数组时,其中 64 位整数会使其太大而无法放入主内存,而较少的项目会适合缓存。最简单的方法是禁用与#pragma pack 或__attribute__((packed)) 的对齐
struct int40_t {
int64_t : 40;
} __attribute__((packed));
int40_t myArray[200] __attribute__((packed));
或从一个简单的字符数组中访问值(基于cmm's solution)
unsigned char _5byteInts[5*size+3]; // +3 avoids overfetch of last element
int64_t get5byteInt(size_t index)
{
int64_t v = 0;
memcpy(&v, &_5byteInts[index*5], 5); // little endian
return (v << 24) >> 24;
}
void set5byteInt(size_t index, int64_t value)
{
memcpy(&_5byteInts[index*5], &value, 5); // little endian
}
但是这些会导致在没有未对齐访问的架构上性能不佳。您可以将四个 40 位整数打包到一个 20 字节的结构中以更好地对齐
struct four_int40s {
uint32_t low[4];
uint8_t hi[4];
};