相关疑难解决方法(0)

什么是uint_fast32_t以及为什么要使用它来代替常规int和uint32_t?

因此,对于其原因typedef:ED原始数据类型是抽象低级别表示,并使其更容易理解(uint64_t而不是long long类型,这是8个字节).

但是,有uint_fast32_t与之相同typedefuint32_t.使用"快速"版本会使程序更快吗?

c c++ types

99
推荐指数
3
解决办法
4万
查看次数

在C/C++中无符号左移之前掩盖是否过于偏执?

这个问题的动机是我在C/C++中实现加密算法(例如SHA-1),编写可移植平台无关的代码,并彻底避免未定义的行为.

假设标准化的加密算法要求您实现此目的:

b = (a << 31) & 0xFFFFFFFF
Run Code Online (Sandbox Code Playgroud)

where ab是无符号的32位整数.请注意,在结果中,我们丢弃高于最低32位的任何位.


作为第一个天真的近似,我们可以假设int在大多数平台上都是32位宽,所以我们写:

unsigned int a = (...);
unsigned int b = a << 31;
Run Code Online (Sandbox Code Playgroud)

我们知道这个代码无处不在,因为int在某些系统上是16位宽,在其他系统上是64位,甚至可能是36位.但是使用stdint.h,我们可以使用以下uint32_t类型改进此代码:

uint32_t a = (...);
uint32_t b = a << 31;
Run Code Online (Sandbox Code Playgroud)

所以我们完成了,对吧?这就是我多年来的想法.... 不完全的.假设在某个平台上,我们有:

// stdint.h
typedef unsigned short uint32_t;
Run Code Online (Sandbox Code Playgroud)

在C/C++中执行算术运算的规则是,如果类型(例如short)比类型更窄int,那么int如果所有值都适合,则它会变宽,unsigned int否则.

假设编译器定义short为32位(带符号)和int48位(带符号).然后这些代码行:

uint32_t a = (...);
uint32_t b = a << …
Run Code Online (Sandbox Code Playgroud)

c c++ undefined-behavior language-lawyer integer-arithmetic

72
推荐指数
4
解决办法
4844
查看次数

如果只需要结果的低部分,那么可以使用哪个2的补码整数运算而不将输入中的高位置零?

在汇编编程中,想要从寄存器的低位计算某些东西是相当普遍的,这些位不能保证将其他位置零.在像C这样的高级语言中,你只需将输入转换为小尺寸,让编译器决定是否需要分别将每个输入的高位归零,或者是否可以在输出之后切断结果的高位.事实.

这是为x86-64的(又名AMD64),出于各种原因尤其常见1,其中的一些是存在于其它的ISA.

我将使用64位x86作为示例,但目的是询问/讨论2的补码和无符号二进制算法,因为所有现代CPU都使用它.(注意,C和C++不保证两个补码4,并且有符号溢出是未定义的行为.)

作为示例,考虑一个可以编译为LEA指令2的简单函数.(在X86-64 SysV的(Linux)的ABI 3,前两个函数参数是rdirsi,与在返回rax. int是一个32位的类型.)

; int intfunc(int a, int b) { return a + b*4 + 3; }
intfunc:
    lea  eax,  [edi + esi*4 + 3]  ; the obvious choice, but gcc can do better
    ret
Run Code Online (Sandbox Code Playgroud)

gcc知道即使是负有符号整数,加法也只是从右到左,所以输入的高位不会影响进入的内容eax.因此,它保存了一个指令字节并使用 lea eax, [rdi + rsi*4 + 3]

哪些其他操作具有结果低位的这种属性而不依赖于输入的高位?

为什么它有效?



脚注

1为什么x86-64频繁出现这种情况:x86-64有可变长度指令,其中额外的前缀字节改变了操作数大小(从32到64或16),因此在指令中通常可以保存一个字节.以相同的速度执行.当写入低8b或16b的寄存器(或稍后读取完整寄存器(Intel pre-IvB)时的失速)时,它也具有错误依赖性(AMD/P4/Silvermont):由于历史原因, …

binary x86 assembly integer twos-complement

12
推荐指数
1
解决办法
928
查看次数

长长在 c99

在 C99 标准中,他们引入了long long. 这样做的目的是什么?在我(有限的)C 编程经验中,我只见过 4 字节的 int 和 8 字节的 long。例如,从编译器资源管理器: 在此处输入图片说明

如果long已经是8,为什么还需要添加另一种long long类型?这对编译器/架构有什么影响?

c assembly types abi long-long

8
推荐指数
1
解决办法
333
查看次数