C4244:'+ =':从'std :: streamsize'转换为'size_t',可能会丢失数据

时间:2016-01-06 12:20:06

标签: c++ visual-c++ visual-studio-2013

我已将我的VC ++项目表单VS2008迁移到VS2013并收到一些警告:

  

C4244: '+=' : conversion from 'std::streamsize' to 'size_t', possible loss of data.

如何解决这些类型的警告?

3 个答案:

答案 0 :(得分:1)

正如c++ reference中所述,std::streamsize被定义为signed(强调我的):

  

类型std::streamsize是一个带符号的整数类型,用于表示在I / O操作中传输的字符数或I / O缓冲区的大小。它用作std::size_t签名对应项,类似于POSIX类型ssize_t

无论如何,似乎没有具体说明。

通常,从signedunsigned类型的转换具有相同的基数(例如long)不应发出有关可能的数据丢失的警告(除非使用符号指示符是意)。

它可能是Visual Studio C ++中糟糕的实现。

答案 1 :(得分:1)

在MSVC 2013中std::streamsize是:

typedef _Longlong streamsize;
typedef _LONGLONG _Longlong;
#define _LONGLONG   __int64

size_t是:

typedef unsigned __int64    size_t;

因此,一个简单的责备案例是:

unsigned __int64 b = 1;
__int64 a = b;

然而,这不会发出警告 - 所以你可能在某处将size_t重新定义为32位?

为清楚起见:

std::streamsize b = 1;
size_t a = 0;
b = a;

也没有发出警告。

答案 2 :(得分:0)

这取决于用途。根据{{​​3}},

除了std :: strstreambuf的构造函数外,从不使用std :: streamsize的负值。

因此,您可以放心地使用已签名的值。

std::streamsize i;
// ...
size_t u = static_cast<size_t>(i);

但是,在更一般的情况下(与πάνταῥεῖ写的相反),我认为警告是有效的(即使gcc不会吐出类似的警告)。比较有符号和无符号值时,最好明确您的意思。

您可以强制取消签名,例如使用如下代码段(感谢cppreference.com的一般形式):


#include <iostream>

template <typename T>
typename std::enable_if< std::is_signed<T>::value, typename std::make_unsigned<T>::type >::type
force_unsigned(T u) {
        if (u < 0) {
                throw std::overflow_error("Cannot use negative value as unsigned type");
        }
        return static_cast< typename std::make_unsigned<T>::type >(u);
}

template <typename T>
typename std::enable_if< !std::is_signed<T>::value, T >::type
force_unsigned(T u) {
        return u;
}

int main() {
  std::cout << force_unsigned((unsigned int)1) << std::endl;
  std::cout << force_unsigned((int)1) << std::endl;
  std::cout << force_unsigned((int)0) << std::endl;
  std::cout << force_unsigned((int)-1) << std::endl;
  return 0;
}