不知道这个指针可能指向什么,也无法解释结果
No idea what this pointer could be pointing to and unable to interpret the result
这是在考试中给出的一个过去的问题,但我无法理解最后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
, 0
和0
的值(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这样的小端序机器中,999
的unsigned 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
- 无法解释以下C++代码段的输出
- 数组中无法解释的最后一个项目
- 对于相同的精确计算,无法解释的不同OMP_GET_WTIME()
- C 常量无法解释的行为
- C 无法解释的类“尚未声明”错误,这是由于名称空间而导致的
- [C++]重新定义 y 值的基本数组代码。它正在工作,但无法解释为什么
- std::future::wait 是内存障碍吗?(我无法解释这种数据竞赛)
- unsigned int/signed int/long-long:无法解释的输出
- C++:带有cout和指向char的指针的无法解释的行为
- 我的C++片段中无法解释的断言失败
- C 构造函数中无法解释的调用
- Excel VBA中C++DLL位置存在无法解释的行为
- 无法解释的 VIM 或 GCC 行为
- Marshal.StructureToPtr出现无法解释的内存泄漏
- 为什么这个自定义比较器在构造 std::p riority_queue 时无法解释 std::sort
- QT应用程序无法解释使用SQLite插入功能
- 无法解释的链接器错误
- 无法解释编译器的行为
- C时间混合问题似乎无法解释,以及如何明智地升级代码库
- 不知道这个指针可能指向什么,也无法解释结果