【问题标题】:How does dereferencing the pointer is changing the value in this code snippet?取消引用指针如何更改此代码段中的值?
【发布时间】:2021-07-16 09:06:31
【问题描述】:

有人能解释一下这里发生了什么吗?

#include "iostream"


int main(int argc, char const *argv[]) {

  unsigned long var  = 0x04030201;
  unsigned char* ptr = NULL;

  ptr = (unsigned char*) &var;
  ptr[2] = 0x05;
  std::cout << std::hex << var << '\n';

  return 0;
}

输出:0x4050201

【问题讨论】:

  • 你期望的输出是什么?你认为ptr[2] = 0x05 会做什么?
  • C++ 允许你做各种奇怪的、奇妙的和完全愚蠢的事情。和 C++ 中的许多其他东西一样,这些都是基于上下文的奇怪、美妙和完全愚蠢的变化。

标签: c++ pointers hex dereference


【解决方案1】:

您不仅要取消引用指针,还要更新值。

 ptr[2] = 0x05;

更新第 3 个八位字节的值。所以,对于一个起始值

 (0x) 04 03 02 01

它被修改为

 (0x) 04 05 02 01    
         ^--------- ptr[2]

添加,来自C11,第 6.3.2.3 章,

[...] 当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节。结果的连续递增,直到对象的大小,产生指向对象剩余字节的指针。

所以,在little-endian system 中,它看起来像

ptr[0] = 01
ptr[1] = 02
ptr[2] = 03
ptr[3] = 04 

并且您正在修改ptr[2],因此值更改会反映在结果中。

【讨论】:

  • IIRC std::cout &lt;&lt; var; 由于别名问题导致 UB。代码可能假设 var 没有因 ptr[2] = 0x05; 而改变。
【解决方案2】:

var是一个无符号长变量,在32位系统中为4字节,在64位系统中为8字节。

ptr 是指向无符号字符的指针。 ptr 查看 var 的“第一个”字节,因为它是一个 char 指针。

ptr[2] 在指针算术中为 '*(ptr + 2)',因此该表达式为我们提供了提前 2 个字节的地址并取消引用指针。

所以,最后,十六进制值0x05 将分配给var 的第三个字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 2018-04-06
    • 2013-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 2020-12-01
    相关资源
    最近更新 更多