C4244:“+=”:从“std::streamsize”转换为“size_t”,可能丢失数据
Posted
技术标签:
【中文标题】C4244:“+=”:从“std::streamsize”转换为“size_t”,可能丢失数据【英文标题】:C4244: '+=' : conversion from 'std::streamsize' to 'size_t', possible loss of data 【发布时间】:2016-01-06 12:20:05 【问题描述】:我已将我的 VC++ 项目从 VS2008 迁移到 VS2013,并收到如下警告:
C4244: '+=' : conversion from 'std::streamsize' to 'size_t', possible loss of data.
如何解决这些类型的警告?
【问题讨论】:
warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data -- C++的可能重复 @rkm_Hodor_king 不是真的。 【参考方案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】:正如c++ reference 中所述,std::streamsize
被定义为signed
(强调我的):
std::streamsize
类型是一个有符号整数类型,用于表示在 I/O 操作中传输的字符数或 I/O 缓冲区的大小。它用作std::size_t
的签名副本,类似于POSIX类型ssize_t
。
总之,具体的实现好像没有具体说明。
通常,从signed
到具有相同基数的unsigned
类型(例如long
)的转换不应发出有关可能丢失数据的警告(除非使用符号指示符)。
这在 Visual Studio C++ 中可能是一个糟糕的实现。
【讨论】:
unsigned int u = (int)-1;
怎么样?你希望u
是什么?你会考虑这种数据丢失吗?编译器应该发出警告吗?【参考方案3】:
这取决于用途。根据cppreference.com,
除了在 std::strstreambuf 的构造函数中,从不使用 std::streamsize 的负值。
所以你可以安全地转换你的签名值。
std::streamsize i;
// ...
size_t u = static_cast<size_t>(i);
但是,在更一般的情况下(与 πάντα ῥεῖ 所写的相反),我认为警告是有效的(即使 gcc
没有吐出类似的警告)。在比较有符号和无符号值时,最好明确您的意思。
您可以强制无符号,例如使用如下代码 sn-p(感谢this question 的一般形式):
#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;
【讨论】:
以上是关于C4244:“+=”:从“std::streamsize”转换为“size_t”,可能丢失数据的主要内容,如果未能解决你的问题,请参考以下文章
编译器错误 C4244:“正在初始化”:从“__int64”转换为“int”,可能丢失数据
如何为 std::vector 复制或使用隐式缩小转换禁用 Visual Studio 警告 C4244
提升 microsec_time_clock.hpp 警告 C4244