C编程:来自字节数组的单词

Ube*_*son 1 c arrays pointers bit-manipulation

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

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

uint8_t *mem;
//...
mem = calloc(MEM_SIZE, sizeof(uint8_t)); // MEM_SIZE is pre defined as 1024x1024
Run Code Online (Sandbox Code Playgroud)

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

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

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

uint32_t foo = *(uint32_t*)(mem+mipsaddr);
printf("foo = 0x%08x\n", foo);
Run Code Online (Sandbox Code Playgroud)

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

    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);  
Run Code Online (Sandbox Code Playgroud)

上面代码的输出如下:foo = 0x84100000 test4 = 0x00001084

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

我是新来的,我确实在寻找这个问题的答案但却找不到.如果它已经发布,我道歉!但如果没有,我希望有人可以在这里启发我.

And*_*ter 5

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

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

在你的for循环中,你是按字节顺序存储你的值,从最重要的字节开始(倒计时索引有点误导;-).之后你的记忆如下:0x00 0x00 0x10 0x84.

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

在你的第二个方法,你使用你保存个人字节顺序相同(最显著第一),所以你回来,你以前存储的值相同.