我正在读一本关于汇编的书,这里有一句我不太理解的话。它说,访问最低有效位的最有效方法是使用以下代码:
*(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
:
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快,因为读取一个字节实际上意味着两个操作:读取4、截断&展开符号。
也许你在转录/转述这本书的内容时出错了。
首先,
*(unsigned char*)&a
一点也不访问。它访问一个字节。
其次,不一定是意义最小的字节。它是小端序系统中最不重要的字节。在大端序系统中,它是最重要的字节。
在任何一种情况下,它都访问整数的最低寻址字节。