不知道这个指针可能指向什么,也无法解释结果

No idea what this pointer could be pointing to and unable to interpret the result

本文关键字:什么 无法解释 结果 指针 不知道      更新时间:2023-10-16

这是在考试中给出的一个过去的问题,但我无法理解最后4个printf函数获得的结果。我得到了前两个字符的十六进制转换但我真的不明白

上的字符是怎么来的
ptr[0] to ptr[3]

这是编译并运行的代码段。

int main(int argc, char *argv[]){
    typedef unsigned char byte;
    unsigned int nines = 999;
    byte * ptr = (byte *) &nines;
    printf ("%xn",nines);
    printf ("%xn",nines * 0x10);
    printf ("%dn",ptr[0]);
    printf ("%dn",ptr[1]);
    printf ("%dn",ptr[2]);
    printf ("%dn",ptr[3]);
    return EXIT_SUCCESS;
}

,这是相应的输出

3e7
3e70
231
3
0
0

当您执行byte * ptr = (byte *) &nines;时,您将ptr的地址设置为nines的相同地址。它的值是999,十六进制是0x3e7

从问题中,我假设int有4个字节,这是一个小端序系统。也就是说,字节是这样存储的。

---------------------------------
| 0xe7  |  0x03 |  0x00 |  0x00 |
---------------------------------
  ptr     ptr+1   ptr+2    ptr+3

因此,当您将它们打印出来时,您将得到231, 3, 00的值(231等于0xe7)

在小端序系统中,首先存储最低有效位字节,最后存储最高有效位字节,这是intel处理器和今天大多数微控制器所遵循的。

另一方面,我们有大端系统,其次是一些旧的摩托罗拉控制器和功率PC。在这种方法中,首先存储最高位字节。这些系统的输出将是0、0、3和231。

此代码依赖于平台。

假设你的平台是:

  • 小端字节序
  • CHAR_BIT == 8
  • sizeof(int) == 4

999在内存中的二进制表示为11100111 00000011 00000000 00000000

因此999在内存中的十进制表示为231 3 0 0


作为一个旁注,你应该提请你在学校/学院/大学的老师注意,由于这段代码是平台相关的,所以作为考试的一部分给出它是一个非常糟糕的例子。

如果你有这样的考试,我建议你尽快更换讲师。

unsigned int的表示是实现指定的,它取决于您的机器的大小,字节序。

无论如何,从unsigned int*转换到char*然后直接读取它的值应该是一个未定义的行为。

在像x86这样的小端序机器中,999unsigned int表示为:

| 0xE7 | 0x03 | 0x00 | 0x00 |
-----------------------------
  ptr    ptr+1  ptr+2  ptr+3
编号在|之间的

为该byte中的值。因此,它将被打印为:

231 3 0 0

在另一台机器上,假设是32位的大端字节(例如Atmel AVR32),它将被表示为:

| 0x00 | 0x00 | 0x03 | 0xE7 |
-----------------------------
  ptr    ptr+1  ptr+2  ptr+3

则输出:

0 0 3 231

在另一台机器中,假设是32位,中端,它将被表示为:

| 0x03 | 0xE7 | 0x00 | 0xE0 |
-----------------------------
  ptr    ptr+1  ptr+2  ptr+3

则输出:

3 231 0 0

在旧的机器中,假设是16位小端序机器,它被表示为:

| 0xE7 | 0x03 | xx| xx |
------------------------
  ptr    ptr+1  ptr+2  ptr+3

xx是未指定的值,有另一个未定义的行为。

在64位大端机器中,表示为:

| 0x00| 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x03 | 0xE7
-----------------------------
  ptr    ptr+1  ptr+2  ptr+3

它将打印:

0 0 0 0

也就是说,考试的问题没有确切的答案。如果是,它仍然调用未定义行为。

关于Endianness,未定义行为的进一步阅读

此代码显示数字nines(假定为32位)的每个字节的值。

nines的值十进制为999,十六进制为3E7,根据打印的值,它以小端字节顺序存储(最不重要的字节放在第一位)。

如果将值转换为十六进制,则更容易看到:

printf ("%xn",ptr[0]);
printf ("%xn",ptr[1]);
printf ("%xn",ptr[2]);
printf ("%xn",ptr[3]);

显示如下:

E7
3
0
0

也可以这样解释十进制值:

231 + 3*256 + 0*65536 + 0*16777216 = 999

nines是堆栈上的无符号32位整数(请注意,int可能是64位宽,但这里似乎不是这样)。ptr是一个指针,初始化为nines的地址。由于它是一个指针,因此可以使用数组语法访问所指向的地址处的值。我们假设它是一个小端序机器,所以ptr[0]nines的第一个字节(最低有效),ptr[1]是下一个字节,以此类推。231是最小有效字节的值,在十六进制中是0xe7