【发布时间】:2021-10-21 18:32:42
【问题描述】:
我正在尝试了解 C 和 C++ 的严格别名规则。我已经对此提出了很多问题并阅读了一些内容,但我只是想澄清一些事情。
// void* can alias any other type:
int anInt;
void* pToVoid = (void*)&anInt; // Allowed
// So can char*
char* pToChar = (char*)&anInt; // Allowed
指向任何类型的指针都可以别名为 void*,这就是为什么我们可以这样做:
int* myNewInt = (int*)malloc(sizeof(int));
但是:
(问题1)任何指针类型都可以别名char指针吗?
char myChars[4];
int* pInt = (int*)myChars; // Is this allowed?
// I'm guessing so because this is how we create buffers
float* pFloat = (float*) pInt; // I know this is strict aliasing violation
问题 2:当将任何指针类型别名为 char 或 void 指针类型时,我们需要确保正确对齐,对吗?当我们从 new 或 malloc 获取 char 或 char 数组时,堆栈上不能保证对齐,对吧?
我的第三个问题是,当你强制转换指针或指针对同一内存进行别名时,是否违反了严格的别名规则?例如:
struct MyStruct
{
int myInt;
float myFloat;
};
int main()
{
MyStruct myStructObj;
float* pFloat = &myStructObj.myInt; // This is aliasing the wrong type, not allowed
// However if I move the float* then it no longer aliases the wrong type
pFloat += 1;
// Now the pointer points to the right type. However is it now too late? My program
// has UB because I first aliased the pointer in the first place?
// On the other hand I assume this is allowed though:
float pFloat = (float*)(((char*)&myStructObj.myInt) + sizeof(int));
// This way the float pointer never aliases the int, the int pointer is
// first cast to char*, then char* to float*, which I assume is allowed.
}
换句话说,关于访问相同内存或分配不同指针类型的严格别名规则是什么?因为如果它只是关于内存访问,那么我将 float* 分配给 int* 的示例很好,因为我先移动它,对吧?
编辑:有人指出 C 和 C++ 的别名规则不同,因此我将其标记为关于 C++。
【问题讨论】:
-
也许这有帮助:stackoverflow.com/questions/98650/…。但是根据我的经验......用指针做这种事情最终会咬你。
-
你问的是c还是c++?它们是不同的语言,别名规则不同,请只标记其中一种
-
转换本身不是问题,解引用和算术都是。
-
在en.cppreference.com/w/cpp/language/reinterpret_cast 阅读(或重新阅读)此页面,如果您仍然需要它,请要求澄清 - 您基本上需要将此页面作为答案发布。
-
@RichardCritten 我读过,我仍然没有得到详细的信息。根据上面的评论“转换本身不是问题,取消引用和算术是”。我不明白为什么 int a;浮动 b;浮动* pToFloat = (float*)&a; ((char*)pToFloat) + 4;是非法的。我已经将浮点指针转换为 char*,这对别名很好,我对 char* 进行算术运算,而不是 float*。
标签: c++ strict-aliasing