在基元类型指针之间进行强制转换

Casting between primitive type pointers

本文关键字:转换 之间 类型 指针      更新时间:2023-10-16

是否定义如下:

char* charPtr = new char[42];
int* intPtr = (int*)charPtr;
charPtr++;
intPtr = (int*) charPtr;

intPtr未正确对齐(至少在两种情况中的一种情况下)。把它放在那里是违法的吗?UB在任何阶段都在使用它吗?你怎么能用,怎么不能用?

通常,如果int的对齐要求大于char的对齐要求,则结果是未指定的(5.2.10p7)。结果将是类型为int *的有效值,因此可以用operator<<将其打印为指针或转换为intptr_t

因为结果有一个未指定的值,除非实现指定,否则间接它并对生成的int左值执行左值到右值转换是未定义的行为(未赋值的上下文除外)。转换回char *不一定是往返的。

然而,如果原始char *本身是从int *转换的结果,那么转换到int *算为往返行程的后半部分;在这种情况下,将定义强制转换。

特别地,在上述char *new[]表达式的结果的情况下,我们保证(5.3.4p10)char *指针对于intsizeof(int) <= 42是适当对齐的。由于new[]表达式是从分配函数获得其存储的,因此3.7.4.1p2适用;可以转换void *指针指向具有基本对齐要求的任何完整对象类型的指针,然后用于访问对象[…],这强烈暗示,连同5.3.4p10的注释,new[]表达式返回的char *指针也是如此。在这种情况下,int *是指向未初始化的int对象的指针,因此对其间接执行左值到右值转换是未定义的(3.8p6),但对其间接的赋值是完全定义的。int对象在分配的存储中(3.7.4.1p2),因此将int *转换回char *将产生每1.8p6的原始值。这对于递增的char *指针不适用,因为除非sizeof(int) == 1不是int对象的地址。

当然,首先:指针保证在第一种情况(根据§5.3.4/10和§3.7.4.1/2),并且可能是正确的在两种情况下都对齐。(显然,如果sizeof(int) == 1,但是即使不是这样,实现也不会必须具有对齐要求。)

为了清楚起见:你的演员阵容都是reinterpret_cast

除此之外,这是一个有趣的问题,因为就我看得出来,就有关标准。转换的结果是未指明(根据§5.2.10/7);你甚至不能保证将其转换回CCD_ 31将导致原始价值。(例如,在机器上显然不会其中CCD_ 32小于CCD_ 33。)

当然,在实践中:标准要求CCD_ 34的值对于任何值都充分对齐这可能适合它,所以你保证能够做到:

intPtr = new (charPtr) int;

这与你的演员阵容效果完全相同,因为int的默认构造函数是no-op。(假设sizeof(int) <= 42.)所以很难想象一个实现其中第一部分失效。您应该能够使用CCD_ 37就像任何其他合法获得的CCD_。和将其转换回char*将以某种方式产生的想法与原始char*的值不同荒谬的

在第二部分中,所有的赌注都被取消了:你绝对不能取消引用指针(除非您的实现保证否则),并且也很可能将其转换回到CCD_ 41会产生不同的结果。(想象一个词寻址机器,例如,其中将char*转换为int*四舍五入。然后转换回比原来高CCD_ 45的CCD_。或尝试转换未对齐的指针总是导致在空指针中。)