为什么“从'x*'到'y'失去精度”是一个硬错误,什么是适合旧版代码的解决方案
Why is “cast from ‘X*’ to ‘Y’ loses precision” a hard error and what is suitable fix for legacy code
1。为什么?
像这样的代码曾经有效,这是显而易见的意思。编译器是否允许允许(按规范)使其成为错误?
我知道它的精确度失去了,我会对警告感到满意。但是它仍然具有明确定义的语义(至少定义了未签名的缩小尺寸的演员),并且用户可能只想这样做。
2。解决方法
我有旧的代码,我不想重构太多,因为它很棘手并且已经进行了调试。它正在做两件事:
-
有时将整数存储在指针变量中。如果代码以前存储了整数,则仅将指针投放到整数。因此,尽管演员阵容正在缩小尺寸,但溢出在现实中永远不会发生。该代码经过测试并有效。
当整数存储时,它总是适合普通的旧unsigned,因此更改类型不是一个好主意,并且指针经过很大的传递,因此更改它的类型将有些侵入性。
<</p> -
使用地址作为哈希值。一件相当普遍的事情。哈希表不大,可以扩展类型。
代码使用普通的
unsigned
来实现哈希值,但是请注意,size_t
的常规类型仍然可能生成错误,因为不能保证sizeof(size_t)
> =sizeof(void *)
。在具有分段内存和远处指针的平台上,size_t
只需要覆盖偏移部分。
那么,最不适合侵入性的解决方法是什么?已知该代码在与不产生此错误的编译器编译时可以使用,因此我真的想执行操作,而不是更改。
注意:
void *x;
int y;
union U { void *p; int i; } u;
-
*(int*)&x
和u.p = x, u.i
不是不是等效于(int)x
,而不是(void *)y
的对立面。在大型末端架构上,前两个将在较低地址上返回字节,而后者将以低顺序字节进行工作,该字节可能位于更高的地址上。 -
*(int*)&x
和u.p = x, u.i
都是严格的违规违规行为,(int)x
是。
c ,5.2.10:
4-可以将指针明确转换为任何足够大的积分类型以容纳它。[...]
c,6.3.2.3:
6-任何指针类型都可以转换为整数类型。[...]如果结果无法在整数类型中表示,则行为是不确定的。[...]
,如果int
为32位,而void *
为64位,则(int) p
是非法的。C 编译器是正确的,可以给您错误,而C编译器可能会在翻译上出现错误,或者发出未定义行为的程序。
您应该写,添加一个转换:
(int) (intptr_t) p
或使用C 语法,
static_cast<int>(reinterpret_cast<intptr_t>(p))
如果您要转换为未签名的整数类型,请通过uintptr_t
而不是intptr_t
转换。
这是一个很难解决的"一般",因为" LOSES PROCISION"表示您的指针大于您试图将其存储的类型大。这很可能是"好的:"在您的脑海中,编译器担心您将恢复INT值重新回到指针中,该指针现在已经失去了32位的上限(假设我们在谈论32位INT和64位指针 - 有其他可能的组合)。
有uintptr_t
与系统上的指针兼容大小兼容,因此通常,您可以通过:
int x = static_cast<int>(reinterpret_cast<uintptr_t>(some_ptr));
这将首先迫使指针的大整数,然后将大整数施放为较小的类型。
c
的答案将指针转换为整数正在定义。您的问题是您所谈论的代码似乎永远都不正确。可能只在int
和指针的古代建筑上工作。
如果存在于平台上(通常是这样),则唯一应该不损失的类型是[u]intptr_t
。这种uintptr_t
的哪一部分适合用于您的哈希功能,您不应该对此做出任何假设。我会去做
uintptr_t n = (uintptr_t)x;
,然后
((n >> 32) ^ n) & UINT32_MAX
可以在32位拱门上进行优化,并为您提供64位拱门上所有其他位的痕迹。
对于C 基本上应该适用,只有铸件为reinterpret_cast<std:uintptr_t>(x)
。
- C++从另一个类访问公共静态向量的正确方法是什么
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在另一个类视图中添加最多2个图表的正确方法是什么
- 当我们从/tp地址中添加/减去一个整数时会发生什么
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 将指针分配给另一个指针时会发生什么情况?
- 给定一个整数数组,需要在Max_Heap上运行操作。得到错误"segmentation fault",有什么想法吗?(C++)
- 我正在尝试制作一个程序,在添加 n 天(整数)后告诉一个人什么是一天(例如星期一等)
- 将一个双倍值乘以10会发生什么
- 什么 /可以/ 你从一个函数返回. 并期望它在到达时还活着?
- 如果我向一个12字节的缓冲区写入的字节数少于12,会发生什么情况
- 当一行中只有一个"#"而没有其他内容时,C++预处理器会做什么?
- 如何声明一个标准::提升直方图的向量?提升直方图的类型是什么?
- 当我尝试在函数内声明一个函数时,它不起作用?有什么建议吗?*源代码如下*
- 将(临时的?)std::string传递给使用它来构造一个接受副本的对象的函数的最佳方法是什么?
- 使用只有一个成员的工会的目的是什么?
- 将vector<vector<double>>从x86平台中创建的一个进程发送到x64中构建的另一个进程的最快方法是什么
- 除了调用全局删除运算符之外,删除一个void指针还能做什么呢
- 如果您为类的一个对象动态分配内存作为参数,会发生什么