访问和更改私有类成员的值:
#include <stdio.h>
class hack_Me
{
private:
size_t age;
public:
size_t getAge() const
{
return this->age;
}
explicit hack_Me(size_t age):age(age) { }
};
void change_age(hack_Me* h)
{
*((int*)h) = 100;
}
int main(int argc, char* argv[])
{
hack_Me h(12);
printf("%d \n", h.getAge());
change_age(&h);
printf("%d \n", h.getAge());
getchar();
return 0;
}
在12之后打印100。
适用于MSVC 14。
此行为是否未定义和/或编译器相关?
UPDATE :StackOverflow会为您提供积分吗?
答案 0 :(得分:4)
此行为是否未定义和/或编译器相关?
使用int*
访问类型为size_t
的变量是不好的,无论变量是在类中还是单独存在。
如果您使用
*(reinterpret_cast<size_t*>(h)) = 100;
它不是未定义的行为,它不依赖于编译器。我怀疑,如果你使用它将没有任何不同:
*((size_t*)h) = 100;
您的课程符合标准布局 struct
的要求。
来自C ++ 11标准:
9个课程
...
7标准布局类是一个类:
- 没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员,
- 没有虚函数(10.3),没有虚基类(10.1),
- 对所有非静态数据成员具有相同的访问控制(第11条),
- 没有非标准布局基类,
- 要么在大多数派生类中没有非静态数据成员,要么最多只有一个具有非静态数据成员的基类,或者没有带有非静态数据成员的基类,并且
- 没有与第一个非静态数据成员相同类型的基类。
8 标准布局结构是使用类 - 键
struct
或类 - 键定义的标准布局类em>class
。
对于标准布局 struct
,指向对象的指针可以别名为指向第一个成员变量的指针。
来自C ++ 11标准:
9.2班级成员
...
20指向标准布局结构对象的指针(适当地使用
reinterpret_cast
转换)指向其初始成员(或者如果该成员是位字段,则指向它所在的单位)和反之亦然。 [注意: 因此,在标准布局结构对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐。 - 结束记录]
答案 1 :(得分:1)
在hack_Me中你有size_t age;
,它可能小于int(例如,在8位架构下,它可能是sizeof(size_t)== 1和sizeof(int)== 2)。如果您的编译器在hack_Me的末尾没有生成填充,则可能发生整个hack_Me小于int,因此*((int*)h) = 100;
可能会覆盖比仅hack_Me的第一个成员更多的内存。将hack更改为*((size_t*)h) = 100;
并且可能正常(请参阅其他答案)。