1

我对从字节数组中读取单词有些困惑。背景背景是我正在开发一个用 C 语言编写的用于介绍计算机体系结构类的 MIPS 模拟器,但是在调试我的代码时,我遇到了一个令人惊讶的结果,从 C 编程的角度来看,我根本无法理解。

我有一个名为 mem 的字节数组,定义如下:

uint8_t *mem;
//...
mem = calloc(MEM_SIZE, sizeof(uint8_t)); // MEM_SIZE is pre defined as 1024x1024

在我的一些测试中,我手动将 uint32_t 值存储到四个内存块中,地址为 mipsaddr,一次一个字节,如下所示:

for(int i = 3; i >=0; i--) {
         *(mem+mipsaddr+i) = value;
         value = value >> 8;
         // in my test, value = 0x1084
}

最后,我测试了尝试以两种方式之一从数组中读取单词。第一种方式,我基本上是尝试一次将整个单词读入一个变量:

uint32_t foo = *(uint32_t*)(mem+mipsaddr);
printf("foo = 0x%08x\n", foo);

在第二种方式中,我手动读取每个单元格中的每个字节,然后将它们与位移相加:

    uint8_t test0 = mem[mipsaddr];
    uint8_t test1 = mem[mipsaddr+1];
    uint8_t test2 = mem[mipsaddr+2];
    uint8_t test3 = mem[mipsaddr+3];

    uint32_t test4 = (mem[mipsaddr]<<24) + (mem[mipsaddr+1]<<16) + 
               (mem[mipsaddr+2]<<8) + mem[mipsaddr+3];
    printf("test4= 0x%08x\n", test4);  

上面代码的输出是这样的: foo= 0x84100000 test4= 0x00001084

test4 的值与我预期的完全一样,但 foo 似乎颠倒了字节的顺序。为什么会这样?在 foo 的情况下,我希望 uint32_t* 指针指向 mem[mipsaddr],并且由于它是 32 位长,它只会按照它们在数组中存在的顺序读取所有 32 位(即 00001084) . 显然,我的理解是不正确的。

我是新来的,我确实搜索过这个问题的答案,但找不到。如果已经发过,请见谅!但如果没有,我希望有人能在这里启发我。

4

2 回答 2

5

它(除其他外)在这里解释:http ://en.wikipedia.org/wiki/Endianness

将大于一个字节的数据存储到内存中时,取决于存储字节顺序的架构(即 CPU)。要么首先存储最高有效字节,最后存储最低有效字节,反之亦然。当您通过字节访问操作读回各个字节,然后将它们合并以再次形成原始值时,您需要考虑特定系统的字节序。

在您的 for 循环中,您按字节存储值,从最重要的字节开始(倒数索引有点误导 ;-)。之后你的记忆是这样的:0x00 0x00 0x10 0x84.

然后,您将使用单个 32 位(四字节)访问来回读该字。根据我们的架构,这将成为0x00001084(大端)或0x84100000(小端)。既然你得到后者,你正在研究一个小端系统。

在您的第二种方法中,您使用存储单个字节的相同顺序(首先是最重要的),因此您可以取回与之前存储的相同的值。

于 2012-10-05T05:59:47.800 回答
0

这似乎是字节顺序的问题,可能来自将 (uint8_t *) 转换为 (uint32_t *)

于 2012-10-05T06:05:18.010 回答