使用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
现在,看起来你正在使用ASCII编码,所以这实际上是你在内存中真正拥有的
memAddr | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
data | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x00 |
^ s points here
^ p+1 points here
对于小端机器而言,这意味着多字节类型的最低有效字节排在前面。单个字节的char没有大小端的概念。ASCII字符串只是一串chars,没有大小端之分。int为2个字节。所以对于从内存位置2开始的int,该字节是最不重要的,地址3处的字节是最重要的。这意味着这里读取的数字通常按人们阅读数字的方式来看是0x4443(十进制下为17475,“DC”作为ASCII字符串),因为内存位置3中的0x44比内存位置2中的0x43更重要。当然,在大端模式下,这将被反转,并且数字将是0x4344(十进制下为17220,“CD”作为ASCII字符串)。
回应您的评论...c
字符串是一个以NUL
结尾的char
数组,这是绝对正确的。字节序仅适用于原始类型,如short、int、long、long long
等(“原始类型”可能不正确,知道的人可以纠正我)。数组只是一段连续内存,其中一个或多个类型直接相邻存储,按顺序存储。整个数组没有字节序的概念,但是字节序确实适用于数组中各个元素的原始类型。假设你有以下内容,假设是2字节的int
:
int array[3]
array[0] = 0x1234
array[1] = 0x5678
array[2] = 0x9abc
这就是内存的样子:无论是大端还是小端机器,它的样子都是一样的。
memAddr | 0-1 | 2-3 | 4-5 |
data | array[0] | array[1] | array[2] |
注意,对于数组的元素,不存在字节序的概念。无论元素是什么,都是如此。元素可以是原始类型、结构体等任何类型。数组中的第一个元素始终位于
array[0]
。
但是,现在,如果我们查看实际存储在数组中的内容,这就涉及到字节序的问题。对于小端机器,内存将如下所示:
memAddr | 0 | 1 | 2 | 3 | 4 | 5 |
data | 0x34 | 0x12 | 0x78 | 0x56 | 0xbc | 0x9a |
^______^ ^______^ ^______^
array[0] array[1] array[2]
最不重要的字节排在最前面。大端机器看起来是这样的:
memAddr | 0 | 1 | 2 | 3 | 4 | 5 |
data | 0x12 | 0x34 | 0x56 | 0x78 | 0x9a | 0xbc |
^______^ ^______^ ^______^
array[0] array[1] array[2]
注意数组中每个元素的内容取决于字节序(因为它是原始类型的数组...如果它是结构体数组,结构体成员就不会受到某种字节序反转的影响,字节序仅适用于原始类型)。但是,无论在大端还是小端机器上,数组元素的顺序仍然相同。
回到你的字符串,字符串只是一个以NUL结尾的字符数组。char是单个字节,所以只有一种排序方式。考虑以下代码:
char word[] = "hey";
这是您在内存中拥有的内容:
memAddr | 0 | 1 | 2 | 3 |
data | word[0] | word[1] | word[2] | word[3] |
equals NUL terminator '\0' ^
在这种情况下,word
数组的每个元素都是一个单字节,而且只有一种方式来对单个项目进行排序,因此无论在小端或大端机器上,这就是你在内存中拥有的内容:
memAddr | 0 | 1 | 2 | 3 |
data | 0x68 | 0x65 | 0x79 | 0x00 |
字节序仅适用于多字节原始类型。 我强烈建议在调试器中四处查看以了解其实际效果。 所有流行的IDE都有内存查看窗口,或者使用 gdb 可以打印内存。 在 gdb 中,您可以按字节、半字(2个字节)、字(4个字节)、巨型字(8个字节)等方式打印内存。 在小端机器上,如果将字符串按字节打印出来,您将按顺序看到字母。 按半字打印,您会看到每2个字母“反转”,按字打印,每4个字母“反转”等等。 在大端机器上,所有内容都将按相同的“可读”顺序打印出来。
17989
(十六进制:0x4645
),这对我来说似乎非常正常。 - jwodders
指向 6 个字节。你将p
赋值为s
,但当你打印时却使用了p+1
。假设你的int
是 4 个字节,这将把p
指向'E'
。下一个字节是'F'
,然后接下来的两个字节超出了你分配的空间。但撇开这些不谈,这看起来很好,我的小端打印输出是 0x25004645。0x45 是'E'
,0x46 是'F'
,而 0x00 和 0x25 则是无人区。 - yanoint
(在我的机器上是short
),忘记 UB(未定义行为),看起来仍然不错。我的输出现在是 0x4443,其中0x43是'C'
,0x44是'D'
。我怀疑你把字符串的 ASCII 字符与十六进制值混淆了?你字符串中的每个字符对应一个字节,可以用 2 位十六进制数表示。使用printf
格式说明符"%x"
以十六进制打印。17475 确实是 0x4443,这是小端机器所期望的结果。 - yano