简体   繁体   中英

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

I have migrated my VC++ project form VS2008 to VS2013 and got some warnings like:

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

How can I resolve these type of warnings?

In MSVC 2013 std::streamsize is:

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

And size_t is:

typedef unsigned __int64    size_t;

Thus an easy repro case is:

unsigned __int64 b = 1;
__int64 a = b;

However this doesn't issue a warning - so probably you redefined size_t somewhere to be 32bits?

For clarity:

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

Also issues no warning.

As it's stated in the c++ reference , std::streamsize is defined as signed (emphasis mine):

The type std::streamsize is a signed integral type used to represent the number of characters transferred in an I/O operation or the size of an I/O buffer. It is used as a signed counterpart of std::size_t , similar to the POSIX type ssize_t .

Anyways, the exact implementation seems not to be specified.

Usually a conversion from signed to unsigned type with the same base (eg long ) shouldn't issue a warning about possible data loss (unless using the sign indicator is meant).

It's probably a poor implementation in Visual Studio C++.

It depends on the use. According to cppreference.com ,

Except in the constructors of std::strstreambuf, negative values of std::streamsize are never used.

So you can safely cast your signed value.

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

However, in the more general case (as opposed to what πάντα ῥεῖ wrote), I think the warning is valid (even though gcc doesn't spit a similar one out). When comparing signed and unsigned values, it's best to be explicit what you mean.

You can force unsigned-ness, eg using a code snippet such as the following (thanks to this question for the general form):


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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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