C++ 转换不同容量的整数
我有以下代码:C++ 转换不同容量的整数,c++,C++,我有以下代码: // ---- third party library code ---- struct Point { int16_t x, y; }; void third_party_library__getPoint(Point*); void third_party_library__setPoint(const Point*); // ---- my library code ---- void move_point(int dx, int dy) { Point pt;
// ---- third party library code ----
struct Point { int16_t x, y; };
void third_party_library__getPoint(Point*);
void third_party_library__setPoint(const Point*);
// ---- my library code ----
void move_point(int dx, int dy)
{
Point pt;
third_party_library__getPoint(&pt);
pt.x += dx;
pt.y += dy;
third_party_library__setPoint(&pt);
}
行pt.x+=dx代码>产生警告
从“int”到“int16”的转换,可能会丢失数据
我该怎么办
禁用这些行的警告
将警告源移动到界面:makedx
和dy
int16\t,因此使用move\u point
功能的人将处理此问题
只需将dx
和dy
转换为int16\t即可
添加assert(dx=-0x8000&&“太大的'dx'值”)
并希望在运行调试版本时它会出现
你应该使用dx和dy int16\t,如果你使用它们,你只是在隐藏它,使用你的代码的人不会看到这些警告,也不会意识到问题。因此,让另一方的人来处理警告,至少他们确定了功能。假设您确实知道这里没有bug(变量的位永远不会超过您关心的位15),我会使用一些“强制转换”的变体
在这种情况下,我通常对两种整数类型使用构造函数:
pt.x += int16_t(dx);
这应该让阅读这段代码的人非常清楚,是的,事实上,你确实想要丢弃超过16位的任何位
添加断言(dx)=
-0x8000&“太大的'dx'值”),希望在我运行时它会命中
调试版本
很明显,您必须处理“潜在”错误(顺便说一句,我称之为全面错误)
为了接受警告(知道只有16位数字将被传递到函数),您可以添加一个cast,它表示您在丢弃16个更高的位时正在执行的操作
所有这些都是假设您有一个32或64位平台。如果您的实现无法处理超过int16的数据,那么您应该使用int16。我更喜欢4,但是最佳选择取决于上下文(例如性能考虑)
禁用这些行的警告
这是不好的,因为禁用警告会给代码增加污点(例如,禁用警告的语法取决于编译器)
将警告源移动到接口:make dx和dy int16_t,因此将使用move_point函数的人将处理此问题
这是不好的,因为您可能希望将来升级第三方库而不更改库的接口
只需将dx和dy转换为int16\t
这是不好的,因为它可能会无声地导致溢出(显然)
顺便说一句,仅使用pt.x+=int16_t(dx)
不会“修复”警告;如果要隐藏警告,请使用pt.x=int16\t(pt.x+dx)
(或其他一些强制转换语法)
添加assert(dx=-0x8000&&“太大的'dx'值”),希望在运行调试版本时它会出现
这是一些毛茸茸的语法,但我想这是最无害的(除了语法之外,它唯一的缺点是性能,我们可以忽略它)。您还可以使用以下语法(避免使用幻数):
对我来说,这里有3个相关但不同的点:
A.处理溢出的问题
实际上,这里有两个部分:转换溢出和加法溢出。即使您将int16\t
作为输入,在+=
阶段仍然可能存在溢出,您必须决定如何处理它(当然,您可以简单地忽略它,但这也是一种选择,并有明确的后果)
B.告知用户限制
通过选择您的(3)选项-移动到界面,您将通知用户第一个溢出,而不是第二个溢出。而且,这不是通知用户的唯一方式。有时,更好的方法是在文档中设置“限制”部分,以便立即将其弄清楚
C.避免警告
一旦您决定使用(A),就可以根据您的决定进行转换,从而使编译器满意
你的(1)和(3)本质上是一样的,尽管人们不太喜欢警告。这些选项只回答回避,而不是交易或通知
(2) 忽略第二个溢出,并将第一个溢出发送给用户。因此,它确实避免并部分告知,忽略了交易的一半,将另一半留给用户
(4) 只是告知,与处理和避免无关
我该怎么办?首先,我将决定如何处理溢出-根据应用程序的不同,它可能会有很大的不同,也就是说,它可能是标准的溢出行为或截断到最大可能的值。然后,我会考虑如何正确地通知我的用户——这取决于文档的组织方式,是否可以接受断言/例外等。最后,我会通过检查溢出并根据交易策略行事来避免警告。这实际上是一个比我的建议高得多的建议,假设他可以做到这一点。你不能总是这样。从技术上讲,这不是一个函数样式转换而不是构造函数调用吗?从抽象的角度来看,它们是一样的。:)
assert(int16_t(dx) == dx);