有没有办法得到一个非 8 位的多数据类型?

Is there any way to get a non 8-bit multiple data type?

我知道这是一个奇怪的问题,但我对此有一些想法,这让我很感兴趣。

示例: 我怎样才能得到 31 位数据类型或其他东西?)

现在我认为答案是否定的,你不能。 也许我错了?

您始终可以手动实现任何宽度的换行,例如 a++; a&=0x7fffffff; 将结果屏蔽为 31 位并实现无符号 31 位类型。将符号扩展重做为更宽的类型代价更高,通常是左移然后算术右移,除非语言 and/or 硬件特别支持源宽度。 (例如,ARM 有一个带符号的位域扩展指令,可以提取任意位域并将其符号扩展到完整的整数寄存器中)。

有些 CPU 的字 and/or 字节不是 8 位的倍数,例如PDP-10 有 36 位字。 https://en.wikipedia.org/wiki/36-bit。在该系统上,自然大小为 36 位,而 32 位将是需要额外指令的非标准类型。

could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit.

不,你不能那样做。 据我所知,没有可位寻址内存的 CPU。 任何 load/store 都必须至少对齐到字节边界。 (如今字节可寻址内存几乎是通用的,但一些 DSP 和一些较旧的 CPU(如 DEC Alpha)仅 have/had 字可寻址内存)。

带有位域的 C 将模拟较窄的类型,但带有填充;你无法避免让编译器生成的 asm 接触填充。

例如

struct i31 {
    int i:31;   // note *signed* int
    // 1 bit of padding is implicit on targets with 32-bit int
};

struct i31 inc(struct i31 x) {
    x.i++;
    return x;
}

int extend_to_int(struct i31 x) {
    return x.i;
}

compiles for x86-64 to this (on the Godbolt compiler explorer).

我可能应该使用 gcc -fwrapv 将带符号溢出的行为定义为 2 的补码环绕。我不确定位域的 C 规则是什么,将带符号的结果分配给带符号的位域是否仍会触发 ISO C 和 C++ 中的带符号溢出未定义行为。

# gcc8.2 -O3
inc(i31):
    lea     eax, [rdi+1]
    and     edi, -2147483648   # keep the top bit of the input
    and     eax, 2147483647    # keep the low 31 bits of i++
    or      eax, edi           # merge.
          #   IDK why it can't / doesn't just leave the carry-out in the padding
    ret
extend_to_int(i31):
    lea     eax, [rdi+rdi]     # left shift by 1 (and copy)
    sar     eax                # shift arithmetic right (by 1)
    ret

但是 ARM 很整洁,并且具有比 x86 更好的位域指令。 (几乎所有东西都有比 x86 更好的位域指令)。

# ARM gcc7.2 -march=armv8-a -O3
inc(i31):
    add     r3, r0, #1
    bfi     r0, r3, #0, #31    # bitfield insert to preserve the high bit of the struct
    bx      lr
extend_to_int(i31):
    sbfx    r0, r0, #0, #31    # signed bitfield extract
    bx      lr