这些指针解除引用之间的区别是什么

时间:2017-07-20 02:08:11

标签: c

这是一种你确定它是重复但你需要问的问题。我不知道术语,所以我不知道要搜索什么,我只是根据我给出的例子要求正确的术语。

有人能解释一下这两者之间的区别(好吧,即使只是正确的术语,我也可以自己来区分):

UINT32 v32;
UINT32* v32_ptr = &v32;

UINT16 v16_1 = *(UINT16*)v32_ptr; // Version 1 of dereferencement
UINT16 v16_2 = (UINT16)*v32_ptr; // Version 2 of dereferencement

结果是一样的,但是用例呢?

1 个答案:

答案 0 :(得分:2)

在第一种情况下,您正在向32位指针投射32位指针并解除引用。在第二种情况下,您将取消引用32位指针。

在这两种情况下,您都要分配一个16位变量。

结果并不总是相同,这取决于架构的结束。换句话说,如果架构是little-endian,那么两个16位变量应该在源可以采用的整个值范围内相等。但如果架构是大端的,那么价值观往往是不同的。

修改 根据下面评论中的问题,我认为一个例子在这里会有所帮助。

考虑以下因素并假装架构可以选择它喜欢的端点。另外,让我们使用值0x4241,并让进程将其写入4次交替的big / little-endian,前两次作为UINT32,最后两次作为UINT16。

address     data
0xABCD0000  00 00 42 41 // big-endian, UINT32, value 0x4242
0xABCD0004  41 42 00 00 // little-endian
0xABCD0008  42 41       // big-endian UINT16
0xABCD000A  41 42       // little-endian UINT16

最后两个是帮助可视化差异。

当我们将v32_ptr设置为v32的地址时,它会收到内存地址0xABCD0000(例如)。该值在内存中布局。如果我们将v32_ptr转换为(UINT16 *),则内存地址不会改变,但现在只使用前两个字节。将该指针解除引用为16位指针将产生0.但是将其解除引用为32位ptr将产生结果0x4241。

现在对little-endian变量做同样的事情。这里我们的内存地址是0xABCD0004和0xABCD000A。将v32_ptr设置为0xABCD0004,并将其解除引用为(UINT16 *)(LE),得到值0x4241。如果您取消引用16位LE指针(如地址0xABCD000A),那么这个值就相同。

两个演员都会截断32位原始值,但我希望你现在可以看到差异。

<强>最后

此信息适用于网络编程,嵌入式系统以及对等和客户端 - 服务器协议。 Little-endian几乎是通用的,但仍然存在BE系统。此外,一些较旧的网络协议明确选择使用BE。并且,您的示例的特定应用程序可能是测试您正在运行的系统的字节序(对于可移植源代码)。即,设置v32 = 0x4241,然后在解除引用两种方式后,如果v16_1和v16_2相同(它们都等于0x4241),则系统为LE,但如果它们不同(一个产生0x4241而另一个产生0),则系统是BE。