【问题标题】:Pointers in C++, Raw Memory OperationsC++ 中的指针,原始内存操作
【发布时间】:2018-05-19 17:44:25
【问题描述】:

我对以下 sn-p 代码有几个不同的问题,这是我的一位教授给出的示例。

首先,Thing t{8,15} 是什么?这是一个包含两个整数 8 和 15 的数组吗? 或者这是否将 t(Thing 类型的变量)的 x 和 y 值分别初始化为 8 和 15? 二、上线是什么情况:

std::cout << "n\t = " << place[0] << ", " << place[1];

在我看来它正在打印变量 place 的索引,据我理解,它是一个指向 int 的指针,指向 t 的内存地址处的整数值?

最后,这条线上到底发生了什么:

 int y = *( int *)(( char *)& t + 4);

我在这里迷路了。请多多包涵,学习指点和记忆

我正在处理的代码:

struct Thing {
int x , y ;
int* getPlaces () {
    return & x ;
}
};

int main () {

Thing t {8 ,15};
int* place = (int *)& t ;
std :: cout << "\nt = " << place [0] << ", " << place [1];
int y = *( int *)(( char *)& t + 4);
std :: cout << "\nt.y = " << y ;
int* location = t . getPlaces ();
location [0] = 17;
std :: cout << "\nt.x = " << t . x ;

}

【问题讨论】:

  • *( int *)(( char *)&amp; t + 4) 很讨厌,并且以一种糟糕的方式破坏了 严格的别名place 的使用也是如此。如果您的教授给了您该代码,您应该告诉他或她。
  • 我认为这个练习的重点是自己运行代码并查看结果,然后用它来获得理解。
  • @SomeProgrammerDude 它像罪一样丑陋,但不是严格的别名违规,因为该内存位置已经有一个 int 对象。
  • @Frank 这是违规行为,因为代码将t 视为两个int 值的数组,但事实并非如此。 &amp;t 指向 int 并不重要。 &amp;t 是指向 Thing 的指针,而不是指向 int 的指针,这就是它崩溃的地方。转换为char*可能解决它,但我不太确定。
  • @SomeProgrammerDude 是的,我同意,地点确实是违规行为,我只是在评论您评论的第一部分,抱歉造成混淆。将 g 转换为 char* 确实很好,因为它正在转换为存储。

标签: c++ pointers


【解决方案1】:

{8,15} 是一个初始化列表。因此,Thing t{8,15} 是变量 t 的声明,其类型为 Thing,使用值 8 和 15 进行初始化。成员按声明顺序使用这些值进行初始化,即 x=8 和 y=15。

int* place 是指向 int 的指针的声明,但在 C/C++ 中,指针始终也是数组。因此,您可以为place 指向的变量写place[0],为紧随其后的变量写place[1],依此类推。没有边界检查,所以一定要知道你在做什么。

(some_type) 是(C 风格)演员表。强制转换强制以某种方式解释以下表达式。在您的示例中,&amp;t 采用 t 的地址。然后这个指针被强制解释为指向char 的指针(本质上意味着每个项目都是一个字节)。 IE。当您向该指针添加 4 时,您指向过去的 4 个字节。接下来(向左),这整件事被解释为指向int 的指针。最后(最左边的*),整个东西被取消引用,产生在那个地址找到的任何东西,解释为int

总结:这个例子仅供学习。永远不要在真正的节目中进行这样的编程。该代码取决于 int 是 4 个字节以及 CPU 允许在任何地址上使用 int 的能力。情况并非总是如此。

【讨论】:

  • “[P]指针也总是一个数组”是非常错误的。指针是指针,数组是数组,它们是不同的。但是,数组可能衰减为指向其第一个元素的指针,这就是初学者犯此错误的原因。
  • @Someprogrammerdude 同意了。我应该更准确。
【解决方案2】:
Thing t {8 ,15};

它正在初始化 t。 x 和 y 是 t 的成员,它们被初始化为 8 和 15。

place[0] 和 place[1] 将打印 8 和 15,因为 place 在前一行中指向 t,。

int y = *( int *)(( char *)& t + 4);

t 转换为 (char *) 然后加 4,然后在转换为 int * 后取消引用。它将打印 15。

【讨论】:

  • 值得注意的是,添加一个虚拟方法(或将当前的 getPlaces 声明为虚拟)会破坏一切。
猜你喜欢
  • 2011-09-07
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多