将 int * const 转换为 long int * const 警告
casting int * const to long int * const warning
以前可能有人以其他方式问过这个问题(如果不是我会感到惊讶)但如果是的话我正在努力寻找它。
鉴于:
#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
returns 临时对象。在大多数临时对象(包括这个)上,top-level 类型的不变性是无关紧要的。
这个:
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++ 中没有合法的方法可以将内存块 read/written 同时作为 long int
和 int
。在 C++ 中允许执行的别名(将一种类型视为另一种类型)的数量是有限的,因为违反别名会使某些非常强大的优化变得不可能或不切实际。
许多程序忽略了这一事实,并在您执行此类操作时依赖编译器生成“原始”程序集。他们正在生成表现出未定义行为的代码。
以前可能有人以其他方式问过这个问题(如果不是我会感到惊讶)但如果是的话我正在努力寻找它。
鉴于:
#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
returns 临时对象。在大多数临时对象(包括这个)上,top-level 类型的不变性是无关紧要的。
这个:
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++ 中没有合法的方法可以将内存块 read/written 同时作为 long int
和 int
。在 C++ 中允许执行的别名(将一种类型视为另一种类型)的数量是有限的,因为违反别名会使某些非常强大的优化变得不可能或不切实际。
许多程序忽略了这一事实,并在您执行此类操作时依赖编译器生成“原始”程序集。他们正在生成表现出未定义行为的代码。