我在这个网站http://www.geeksforgeeks.org/little-and-big-endian-mystery/上阅读到了关于小端和大端的表示。
假设我们有一个数字0x01234567,那么在小端字节序中,它被存储为(67)(45)(23)(01),在大端字节序中,它被存储为(01)(23)(45)(67)。
char *s= "ABCDEF"
int *p = (int *)s;
printf("%d",*(p+1)); // prints 17475 (value of DC)
在上面的代码中看到这里的打印值后,似乎字符串存储为(BA)(DC)(FE)。
为什么不像第一个例子那样从LSB到MSB像(EF)(CD)(AB)那样存储呢?我认为endianess意味着多字节内的字节排序。所以排序应该是关于“整个2字节”,就像第二个例子那样,而不是在这2字节内,对吗?
4条答案
按热度按时间biswetbf1#
使用2字节
int
,这是内存中的内容现在,看起来您使用的是ASCII编码,因此这就是内存中 * 实际 * 的内容
所以对于一个小字节序的机器来说,这意味着多字节类型的最低有效字节首先出现。对于一个单字节的
char
来说,没有字节序的概念。一个ASCII字符串只是一个char
的字符串。它没有字节序。你的int
是2个字节。所以对于一个从内存位置2开始的int
,这个字节是最低有效的。地址3的数字是最重要的,这意味着这里的数字,按照人们通常读数字的方式,是0x4443(17475为基数10,“DC”为ASCII字符串),因为内存位置3中的0x44比内存位置2中的0x43更重要。当然,对于大端序,这将反过来,并且该数字将是0x4344(17220以10为基数,“CD”作为ASCII字符串)。编辑:
一个
c
字符串是一个以NUL
结尾的char
数组,这是绝对正确的。字节序只适用于基本类型,short, int, long, long long
,等等。(“原始类型”可能是不正确的命名法,了解的人可以纠正我)数组只是连续内存的一部分,其中1个或多个类型直接彼此相邻出现,这个数组中的所有元素都是按顺序存储的。整个数组中没有字节存储顺序的概念,但是字节存储顺序适用于数组中各个元素的基本类型。假设您有以下内容,假定为2字节int
s:这就是记忆的样子:无论是大字节序还是小字节序的机器,都是这样的
注意,数组 elements 没有字节序的概念。无论元素是什么,这都是正确的。元素可以是基本类型,
structs
,,任何类型。数组中的第一个元素总是在array[0]
。但是现在,如果我们看一看数组中的实际内容,这就是字节序起作用的地方。对于小字节序机器,内存将如下所示:
最不重要的字节排在最前面。一个大字节序机器看起来像这样:
注意,数组中每个元素的 contents 都受endiance的影响(因为它是一个基本类型的数组..如果它是一个
structs
的数组,struct
成员就不会受某种endiance反转的影响,endiance只适用于基本类型)。然而,无论是在big endian机器上还是在little endian机器上,数组元素的顺序都是相同的。回到字符串,字符串就是一个以
NUL
结尾的字符数组。char
是单字节的,所以只有一种方法来排序它们。请看下面的代码:这是你记忆中的内容:
在本例中,
word
数组中的每个元素都是一个字节,并且只有一种方法来对单个项进行排序,因此无论是在小端还是大端机器上,内存中都将包含以下内容:Endianess只适用于多字节原语类型。我强烈建议在调试器中查看这一点。所有流行的IDE都有内存视图窗口,或者使用
gdb
可以print out memory。在gdb
中,可以将内存打印为字节、半字(2个字节),字(4字节),巨字(8个字节)等等。在小字节序机器上,如果你把字符串打印成字节,你会看到字母是按顺序排列的。打印成半字,你会看到每两个字母“颠倒”,打印成字,每4个字母“颠倒”一次,等等。在大端序机器上,它都会以相同的“可读”顺序打印出来。qmb5sa222#
2022年编辑
处理器不知道它在处理什么类型的数据,文本还是数字,所有的东西在内存中都是数字。
(特殊的CPU指令处理浮点数,期望4 / 8...字节符合某种标准,但无论如何,在内存中,它们只是8位字节,值从0到255,就像其他所有东西一样)
传统上
文本“ABCDEF”在内存中显示为(十六进制)(在C中,编译器在“F”后面添加一个字节0)
在一个2字节的
int
小端系统上,在i
变量中阅读p+1
(您的示例),因为它是小端系统
i
值为读取的第一个字节是
int
的最低有效字节(0x 43),下一个字节是最高有效字节(MSB,0x 44)。请注意,在big-endian系统上,它将是
现在,也许你想在内存中存储数字
0xABCDEF
(十六进制,十进制11259375),我们至少需要一个32位的int来将这个值存储在一个变量中;假设编译器long
类型有32位。在内存中(小端序),数字的存储方式如下
请注意,还有一个“尾随”0,但在这种情况下,它是该数字的MSB,在32位上为0。
在这种情况下,您会找到您所期望的(EF)(CD)(AB),因为编译器将代码字0xABCDEF视为一个数字。在另一种情况下,编译器将文本“ABCDEF”视为一个字符串。
2017年原始答案
字符串之间似乎有点混淆
而以十六进制表示的数字11,259,375是
在第一种情况下,每个字母占用整个字节。
在第二种情况下,我们有六个十六进制数字;一个十六进制数字占用4位,因此在一个字节中需要两个数字。
1.字符'A',然后是'B'等按顺序写入存储器'A'为0x 41,'B'为0x 42...如果
1.这是一个多字节整数,其字节顺序取决于体系结构。假设该数是4字节,一个大端序弧将存储在内存(十六进制)00 AB CD EF中; little-endian将按以下顺序存储:EF CD AB 00
大字节序
小字节序
就你而言
由于您的实现具有
sizeof(int) == 2
,因此打印的数字(17475)是0x 4443或“DC”(字符),将0x44
(“D”)作为MSB,将0x43
(“C”)作为LSB,表明您的体系结构是小端字节序。在内存中写入一个字符串(按顺序),并以
int
的形式阅读其中的几个字符,得到一个取决于字节序的数字。h79rfbju3#
字节序在讨论
s
指向的字符常量数组中存储字节时并不起作用。如果检查*s
处的内存,您会发现字节'a'
、'b'
、'c'
...,在小字节序系统中被解释为int
时,它会被解释为"DCBA"
。请记住,每个
char
已经是一个字节,如果你有char const * s = "0xfedcab09";
,并且你在一个小端系统上做了一个printf("%d", *(int const *)s);
,那么它将打印为0x9abcdef在十进制中的任何结果。bkhjykvo4#
此处出现的混淆是由于 * 符号 *。
在***字符串***中,每个字母占用一个完整字节(
char
)。然而,***number***ABCDEF的十六进制表示是不同的,每个数字(“0”..“9”和“A”...“F”)仅表示四位,或半个字节。因此,number
0xABCDEF
是字节序列这就是 endianness 成为问题的地方:
int x = { 0xEF, 0xCD, 0xAB };
int x = { 0xAB, 0xCD, 0xEF }
int x = { 0xEF, 0x00, 0xCD, 0xAB }