以前可能已经以其他方式提出了这个问题(如果不是这样的话,我会感到惊讶),但是我很难找到它。
鉴于:
#include <iostream>
#include <string>
int main()
{
int * const pi = new int(1);
long int * const pl = reinterpret_cast<long int * const>(pi);
std::cout << "val: " << *pl << std::endl;
return 0;
}
我得到警告:
<source>: In function 'int main()':
<source>:7:27: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers]
7 | long int * const pl = reinterpret_cast<long int * const>(pi);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ASM generation compiler returned: 0
<source>: In function 'int main()':
<source>:7:27: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers]
7 | long int * const pl = reinterpret_cast<long int * const>(pi);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Execution build compiler returned: 0
Program returned: 0
val: 1
但我不确定为什么会收到此警告,因为重铸也应该是const指针-只是指向其他类型。我想实现相同的代码(如果忽略警告,则可以使用),但是没有警告。
long int * const
是指向可变数据的不变指针。
reinterpret_cast
返回一个临时对象。在大多数临时对象(包括该对象)上,顶级类型的不变性是无关紧要的。
这个:
long int * const pl = reinterpret_cast<long int * const>(pi);
是相同的
long int * const pl = reinterpret_cast<long int *>(pi);
编译器警告你,因为想必你以为打字const
有做了什么,你是错的,它什么也没做。
现在,这与您的要求没有直接关系,但是如果我不提及这一点,我将不为所动:
std::cout << "val: " << *pl << std::endl;
导致您的程序表现出不确定的行为。指向的对象不是long int
,它是int
,并且您以其类型不是该对象的形式访问它。
reinterpret_cast
尽管许多人都将其视为“字节”,但它不是“将这些字节作为不同的类型进行处理”。在C ++标准下,此类操作几乎总是未定义的行为。
将对象A的字节解释为类型B的对象(当它们是普通类型时)的正确方法是使用memcpy
。
int * const pi = new int(1);
long int l = 0;
static_assert( sizeof(*pi) == sizeof(l) );
::memcpy( &l, pi, sizeof(l) ); // or l = std::bit_cast<long int>(*pi) in C++20
std::cout << "val: " << l << std::endl;
如果实现定义了输出,这是合法的,因为您可以随意复制足够琐碎的类型的字节,并且long int
必须没有陷阱值。
在C ++中,没有合法的方法可以将内存块作为along int
和作为a进行读取/写入int
。允许在C ++中使用别名(将一种类型当作另一种类型)的数量是有限的,因为违反别名会使某些真正强大的优化变得不可能或不切实际。
当您执行此类操作时,许多程序会忽略此事实,而是依靠编译器生成“幼稚”程序集。他们正在生成表现出未定义行为的代码。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句