访问整数最低有效位的最快方法?
fastest way to access the least significant bit of an integer?
我在看一本关于汇编的书,这里有一个我不太明白的说法。它说访问最低有效位的最有效方法是使用以下代码:
*(unsigned char*)&a
谁能给我解释一下为什么这么快?
有人告诉我,我需要很好地理解汇编才能得到这个。
也许你transcribing/paraphrasing书上说的有误。
首先,
*(unsigned char*)&a
有点访问不了。它访问一个字节。
其次,不一定是最低位。它是小端系统中的最低有效字节。在大端系统中,它是最重要的字节。
无论哪种情况,它都访问整数的最低寻址字节。
我会尽力解释。
无论何时将变量存储在内存中,它都有几个重要的属性:
- 地址
- 尺寸
- 类型
根据你的问题,我怀疑你问的是大小大于 1 的整数变量。例如,int
类型由 C 标准定义为 fast
和 at least 16 bit
.这使得它有 2 到 4 个字节。
所以,让 int
的大小为 4。
那么我们知道,变量占用四个字节,有一些起始地址(&a
):addr+0,addr+1,addr+2,addr+3.
在谈论 C 约定时,您可以将指针从一种类型转换为另一种类型,并使用它来访问数据(假设您知道自己在做什么)。在我们的例子中,我们知道 char
只有 1 个字节长。所以我们可以使用直接内存访问从单个 int
中提取 4 char
s:
char ch0 = *((char *)&a + 0); // OR ((char*)&a)[0]
char ch1 = *((char *)&a + 1); // OR ((char*)&a)[1]
char ch2 = *((char *)&a + 2); // OR ((char*)&a)[2]
char ch3 = *((char *)&a + 3); // OR ((char*)&a)[3]
现在我们有 4 个字节,问题是:哪个字节包含哪些值。即,当我们的 a
等于 0x12345678
时,我们可能有多种替代方法,不同部分在内存中的排序方式。
在 x86 上(与你的情况足够接近),顺序是这样的,所以我们的 int
(0x78) 的最低部分首先存储,然后是第二个,依此类推:
a : 0x12345678
((char*)&a)[0] : 0x78
((char*)&a)[1] : 0x56
((char*)&a)[2] : 0x34
((char*)&a)[3] : 0x12
因此,要访问最低有效位,我们需要从最低有效字节开始访问最低有效位。并且,获胜者是 *(char*)&a
。但是位值为:
*(char*)&a & 1
现在,关于为什么它不完全正确。即使在 x86 上。与我们谈论真正的 8 位处理器不同,许多处理器的设计经过优化,可以在匹配寄存器大小时以最快的方式访问对齐数据。所以如果处理器有 32 位寄存器,它很可能读取 4 个字节比 1 个快,因为读取一个实际上意味着 2 个操作:读取 4,截断和扩展符号。
我在看一本关于汇编的书,这里有一个我不太明白的说法。它说访问最低有效位的最有效方法是使用以下代码:
*(unsigned char*)&a
谁能给我解释一下为什么这么快?
有人告诉我,我需要很好地理解汇编才能得到这个。
也许你transcribing/paraphrasing书上说的有误。
首先,
*(unsigned char*)&a
有点访问不了。它访问一个字节。
其次,不一定是最低位。它是小端系统中的最低有效字节。在大端系统中,它是最重要的字节。
无论哪种情况,它都访问整数的最低寻址字节。
我会尽力解释。
无论何时将变量存储在内存中,它都有几个重要的属性:
- 地址
- 尺寸
- 类型
根据你的问题,我怀疑你问的是大小大于 1 的整数变量。例如,int
类型由 C 标准定义为 fast
和 at least 16 bit
.这使得它有 2 到 4 个字节。
所以,让 int
的大小为 4。
那么我们知道,变量占用四个字节,有一些起始地址(&a
):addr+0,addr+1,addr+2,addr+3.
在谈论 C 约定时,您可以将指针从一种类型转换为另一种类型,并使用它来访问数据(假设您知道自己在做什么)。在我们的例子中,我们知道 char
只有 1 个字节长。所以我们可以使用直接内存访问从单个 int
中提取 4 char
s:
char ch0 = *((char *)&a + 0); // OR ((char*)&a)[0]
char ch1 = *((char *)&a + 1); // OR ((char*)&a)[1]
char ch2 = *((char *)&a + 2); // OR ((char*)&a)[2]
char ch3 = *((char *)&a + 3); // OR ((char*)&a)[3]
现在我们有 4 个字节,问题是:哪个字节包含哪些值。即,当我们的 a
等于 0x12345678
时,我们可能有多种替代方法,不同部分在内存中的排序方式。
在 x86 上(与你的情况足够接近),顺序是这样的,所以我们的 int
(0x78) 的最低部分首先存储,然后是第二个,依此类推:
a : 0x12345678
((char*)&a)[0] : 0x78
((char*)&a)[1] : 0x56
((char*)&a)[2] : 0x34
((char*)&a)[3] : 0x12
因此,要访问最低有效位,我们需要从最低有效字节开始访问最低有效位。并且,获胜者是 *(char*)&a
。但是位值为:
*(char*)&a & 1
现在,关于为什么它不完全正确。即使在 x86 上。与我们谈论真正的 8 位处理器不同,许多处理器的设计经过优化,可以在匹配寄存器大小时以最快的方式访问对齐数据。所以如果处理器有 32 位寄存器,它很可能读取 4 个字节比 1 个快,因为读取一个实际上意味着 2 个操作:读取 4,截断和扩展符号。