通过指针访问结构
accessing struct by a pointer
我目前正在试验指针,我对我的代码有几个问题
ps。这只是为了试验我不会在任何代码中使用它
#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: %d\n", (int)*(long long int*)(*Adress + sizeof(int)));
printf("get value from struct: %d\n", MyStruct.IntPtr[1]);
return 0;
}
为什么 std::cout 使我的程序崩溃?我不得不使用 printf 函数来解决这个问题
我可以从我的主函数中删除 IntPtr 吗?像 delete[] (long long int*)*Adress;
然后创建新的?喜欢:
int* Itemp = new int[5];
*地址 = (long long int)Itemp;
编辑:这只是一个关于如何访问 strcut obj
中的 int* IntPrt
的实验,当它是 private:
时我不会使用这种方法。
即使使用 delete[]
和 new
的代码在我的编译器上也能正常工作
谢谢大家的解释
即使您的代码中的语法错误得到修复,我怀疑您尝试做的事情的前提仍然存在根本性缺陷。获取一个指针,将其转换为表示内存地址的数字,将其四处移动以落在另一个对象上并以这种方式访问它,这在 C++ 中是不允许的。
编译器被允许并积极地基于程序从不做这样的事情的假设来优化代码。因此,即使 if 一个程序在执行此操作时似乎正在运行,但当使用不同的编译器、同一编译器的不同版本或同一编译器的不同编译设置进行编译时,它很可能会中断编译器。
那么这对我们程序员意味着什么?指针是内存地址并不意味着我们可以像内存地址一样对待它们(除了一些特定的例外)。
指针指向对象(提醒:即使是一个简单的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: %d\n", obj->IntPtr[1]);
printf("get value from struct: %d\n", 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;
}
我目前正在试验指针,我对我的代码有几个问题
ps。这只是为了试验我不会在任何代码中使用它
#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: %d\n", (int)*(long long int*)(*Adress + sizeof(int)));
printf("get value from struct: %d\n", MyStruct.IntPtr[1]);
return 0;
}
为什么 std::cout 使我的程序崩溃?我不得不使用 printf 函数来解决这个问题
我可以从我的主函数中删除 IntPtr 吗?像
delete[] (long long int*)*Adress;
然后创建新的?喜欢:int* Itemp = new int[5]; *地址 = (long long int)Itemp;
编辑:这只是一个关于如何访问 strcut obj
中的 int* IntPrt
的实验,当它是 private:
时我不会使用这种方法。
即使使用 delete[]
和 new
的代码在我的编译器上也能正常工作
谢谢大家的解释
即使您的代码中的语法错误得到修复,我怀疑您尝试做的事情的前提仍然存在根本性缺陷。获取一个指针,将其转换为表示内存地址的数字,将其四处移动以落在另一个对象上并以这种方式访问它,这在 C++ 中是不允许的。
编译器被允许并积极地基于程序从不做这样的事情的假设来优化代码。因此,即使 if 一个程序在执行此操作时似乎正在运行,但当使用不同的编译器、同一编译器的不同版本或同一编译器的不同编译设置进行编译时,它很可能会中断编译器。
那么这对我们程序员意味着什么?指针是内存地址并不意味着我们可以像内存地址一样对待它们(除了一些特定的例外)。
指针指向对象(提醒:即使是一个简单的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: %d\n", obj->IntPtr[1]);
printf("get value from struct: %d\n", 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;
}