通过指针访问结构体



我目前正在尝试使用指针,我对我的代码有几个问题

p。这只是为了试验,我不会在任何代码中使用

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
struct obj
{
int* IntPtr;
obj()
{
IntPtr = new int[2];
IntPtr[0] = 123;
IntPtr[1] = 456;
}
};
int main()
{
obj MyStruct;
long long int* Adress = (long long int*) & MyStruct; //pointer to a struct
//change value in struct
*(long long int*)(*Adress + sizeof(int)) = 789;
std::cout << "get value by pointer: " << (int)*(long long int*)(*Adress + sizeof(int)) << std::endl; //std::cout crashes my program
printf("get value by pointer: %dn", (int)*(long long int*)(*Adress + sizeof(int)));
printf("get value from struct: %dn", MyStruct.IntPtr[1]);
return 0;
}
  1. 为什么std::cout使我的程序崩溃?我不得不使用printf函数来解决这个问题

  2. 我可以从主函数中删除IntPtr吗?比如delete[] (long long int*)*Adress;,然后创造新的?如:

    int* Itemp = new int[5];* address = (long long int)Itemp;

编辑:这只是一个关于如何在strcut obj中访问int* IntPrt的实验,当它是private:时,我不会使用这种方法。

的代码,即使与delete[]new工作良好在我的编译器

谢谢大家的解释

即使修复了代码中的语法错误,我怀疑您试图做的事情的前提仍然存在根本缺陷。获取一个指针,将其转换为代表内存地址的数字,将其移动到另一个对象上并以这种方式访问它,这在c++中是不允许的。

编译器被允许并且主动地基于程序永远不会做这样的事情的假设来优化代码。因此,即使如果一个程序在这样做时看起来是工作的,当使用不同的编译器、同一编译器的不同版本或同一编译器上的不同编译设置进行编译时,它很可能会中断。

这对我们程序员来说意味着什么呢?指针是内存地址并不意味着我们可以像对待内存地址一样对待它们(有一些特殊的例外)。

指针指向对象(提醒:即使是简单的int也是对象)。指针指向内存是一个实现细节;除非您正在操作底层存储的原始字节,每次操作一个字节。

必须将指针处理为:

  • 不指向对象,在这种情况下,您只能分配,复制或比较它。

  • 指向一个对象,在这种情况下,您也可以使用*->取消对它的引用。

  • 指向一个属于数组的对象,此时,您可以也可以使用[]或指针算术(+,-,等等…)来访问同一数组中的其他对象。

考虑到这一点,下面是你的代码应该是什么样子。这主要是供参考。我知道那不是你想要做的。
struct obj
{
int* IntPtr;
obj()
{
IntPtr = new int[2];
IntPtr[0] = 123;
IntPtr[1] = 456;
}
~obj() 
{
// Btw. If you have a new, ALWAYS have a delete, even in throwaway code.
delete IntPtr[];
}
};
int main()
{
obj MyStruct;

// Get a pointer to the struct
obj* Adress = &MyStruct;

// Change value in struct via the pointer
obj->IntPtr[1] = 789;
(*obj).IntPtr[1] = 789;
std::cout << "get value by pointer: " <<  obj->IntPtr[1] << std::endl; 
printf("get value by pointer: %dn", obj->IntPtr[1]);
printf("get value from struct: %dn", obj.IntPtr[1]);
}

编辑为了完整起见,下面是我解释你想要的代码:

#include <iostream>
#include <cstdint>
#include <cassert>
struct obj {
int IntData[2];
};
int main()
{
obj MyStruct;
// Get a number containing the memory address associated with MyStruct.
// std::uintptr_t is the integer type of the same size as a pointer
std::uintptr_t AdressOfMyStruct = (std::uintptr_t)&MyStruct;
std::cout << "MyStruct lives at: " << AdressOfMyStruct << std::endl;
// Do the same thing for IntData[1]
std::uintptr_t AdressOfIntData1 = (std::uintptr_t)&MyStruct.IntData[1];
std::cout << "MyStruct.IntData[1] lives at: " << AdressOfIntData1 << std::endl;
// recalculate the address of IntData1 as an offset from MyStruct
std::uintptr_t AdressOfIntData1Calculated = AdressOfMyStruct + sizeof(int);
std::cout << "MyStruct.IntData[1] lives at (alt): " << AdressOfIntData1 << std::endl;
// Verify that IntData[1] is where we expect it to be.
assert( AdressOfIntData1Calculated == AdressOfIntData1 );
// ...Everything up to here is valid code...
// WARNING: this may looks like it works, but it is, in fact, Undefined Behavior.
int* PtrToIntData1 = reinterpret_cast<int*>(AdressOfIntData1); 
*PtrToIntData1 = 789;
// WARNING: This is also undefined behavior.
std::cout << "get value by pointer: " << *PtrToIntData1 << std::endl; 
// This is fine, obviously.
std::cout << "get value from struct: " << MyStruct.IntData[1] << std::endl; 
return 0;
}