Sag*_*r P 2 c pointers endianness
我正在阅读来自这个网站http://www.geeksforgeeks.org/little-and-big-endian-mystery/的小端和大端代表.
假设我们有一个数字0x01234567,那么在little endian中它存储为(67)(45)(23)(01),而在Big endian中它存储为(01)(23)(45)(67).
char *s= "ABCDEF"
int *p = (int *)s;
printf("%d",*(p+1)); // prints 17475 (value of DC)
Run Code Online (Sandbox Code Playgroud)
在上面的代码中看到打印值后,似乎字符串存储为(BA)(DC)(FE).
为什么它不像第一个例子那样从LSB存储到(MS)(CD)(AB)到MSB?我认为endianess意味着在多字节内排序字节.那么排序应该是关于"整个2字节",如第二种情况,而不是在那2个字节内吗?
使用2个字节int
,这就是你在内存中的含义
memAddr | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
data | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | '\0' |
^ s points here
^ p+1 points here
Run Code Online (Sandbox Code Playgroud)
现在,看起来你正在使用ASCII编码,所以这就是你真正拥有的内存
memAddr | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
data | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x00 |
^ s points here
^ p+1 points here
Run Code Online (Sandbox Code Playgroud)
因此对于小端机器,这意味着首先是多字节类型的最低有效字节.单个字节没有endianess的概念char
.ASCII字符串只是一串char
s ..这没有endianess.你的int
s是2个字节.因此,对于int
从存储器位置2开始,该字节是最不重要的,而地址3处的字节是最重要的.这意味着这里的数字,读取人们通常读取数字的方式,是0x4443(基数10的17475,"DC"作为ASCII字符串),因为内存位置3中的0x44比内存位置2中的0x43更重要.对于大端当然,这将被颠倒,数字将是0x4344(基数为10的17220,"CD"为ASCII字符串).
编辑:
解决你的评论...一个c
字符串是一个NUL
终止的char
s 数组,这是绝对正确的.Endianess仅适用于原始类型short, int, long, long long
等.("原始类型"可能是不正确的命名法,知道的人可以纠正我).数组只是连续内存的一部分,其中一个或多个类型直接相邻发生,顺序存储.整个数组没有endianess的概念,但是endianess 确实适用于数组的各个元素的原始类型.假设您有以下内容,假设为2个字节int
:
int array[3]; // with 2 byte ints, this occupies 6 contiguous bytes in memory
array[0] = 0x1234;
array[1] = 0x5678;
array[2] = 0x9abc;
Run Code Online (Sandbox Code Playgroud)
这就是内存的样子:无论是大型还是小型机器,都会看起来像这样
memAddr | 0-1 | 2-3 | 4-5 |
data | array[0] | array[1] | array[2] |
Run Code Online (Sandbox Code Playgroud)
请注意,数组元素没有endianess的概念.无论元素是什么,都是如此.元素可以是原始类型,structs
任何东西.数组中的第一个元素始终为array[0]
.
但是现在,如果我们看一下阵列中的实际内容,这就是endianess发挥作用的地方.对于一个小端机器,内存将如下所示:
memAddr | 0 | 1 | 2 | 3 | 4 | 5 |
data | 0x34 | 0x12 | 0x78 | 0x56 | 0xbc | 0x9a |
^______^ ^______^ ^______^
array[0] array[1] array[2]
Run Code Online (Sandbox Code Playgroud)
最低有效字节是第一个.一个大端机器看起来像这样:
memAddr | 0 | 1 | 2 | 3 | 4 | 5 |
data | 0x12 | 0x34 | 0x56 | 0x78 | 0x9a | 0xbc |
^______^ ^______^ ^______^
array[0] array[1] array[2]
Run Code Online (Sandbox Code Playgroud)
请注意,数组的每个元素的内容都受到字节序的影响(因为它是一个原始类型的数组..如果它是一个数组structs
,struct
成员不会受到某种字节顺序的反转,字节顺序只适用于原语) .但是,无论是在大端还是小端机器上,数组元素仍然处于相同的顺序.
回到你的字符串,字符串只是一个NUL
终止的字符数组. char
s是单个字节,因此只有一种方法可以对它们进行排序.考虑一下代码:
char word[] = "hey";
Run Code Online (Sandbox Code Playgroud)
这就是你在记忆中所拥有的:
memAddr | 0 | 1 | 2 | 3 |
data | word[0] | word[1] | word[2] | word[3] |
equals NUL terminator '\0' ^
Run Code Online (Sandbox Code Playgroud)
在这种情况下,word
数组的每个元素都是一个字节,并且只有一种方法可以对单个项进行排序,因此无论是在小型还是大型端机上,这都是您在内存中的内容:
memAddr | 0 | 1 | 2 | 3 |
data | 0x68 | 0x65 | 0x79 | 0x00 |
Run Code Online (Sandbox Code Playgroud)
Endianess仅适用于多字节基本类型.我强烈建议在调试器中查看,以便在实际操作中看到这一点.所有流行的IDE都有内存视图窗口,或者gdb
你可以打印出内存.在gdb
你可以打印内存为字节,半字(2字节),字(4字节),巨型字(8字节)等.在小端机器上,如果你打印出字符串作为字节,你会看到字母为了.打印成半字,你会看到每2个字母"反转",打印成文字,每4个字母"反转"等.在大端机器上,它将以相同的"可读"顺序打印出来.
归档时间: |
|
查看次数: |
1059 次 |
最近记录: |