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”的转换,可能会丢失数据

我该怎么办

  • 禁用这些行的警告
  • 将警告源移动到界面:make
    dx
    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);