繁体   English   中英

C4244:“+=”:从“std::streamsize”到“size_t”的转换,可能丢失数据

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

我已经将我的 VC++ 项目从 VS2008 迁移到 VS2013 并收到一些警告,例如:

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

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

在 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;

也不发出警告。

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

类型std::streamsize是有符号整数类型,用于表示 I/O 操作中传输的字符数或 I/O 缓冲区的大小。 它用作std::size_t的签名副本,类似于 POSIX 类型ssize_t

无论如何,似乎没有指定确切的实现。

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

这可能是 Visual Studio C++ 中的一个糟糕实现。

这取决于用途。 根据cppreference.com

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

所以你可以安全地转换你的签名值。

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

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

您可以强制使用无符号性,例如使用如下代码片段(感谢一般形式的这个问题):


#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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM