Search code examples
c++signedsize-t

How to detect negative number assigned to size_t?


This declaration compiles without warnings in g++ -pedantic -Wall (version 4.6.3):

std::size_t foo = -42;

Less visibly bogus is declaring a function with a size_t argument, and calling it with a negative value. Can such a function protect against an inadvertent negative argument (which appears as umpteen quintillion, obeying §4.7/2)?

Incomplete answers:

Just changing size_t to (signed) long discards the semantics and other advantages of size_t.

Changing it to ssize_t is merely POSIX, not Standard.

Changing it to ptrdiff_t is brittle and sometimes broken.

Testing for huge values (high-order bit set, etc) is arbitrary.


Solution

  • The problem with issuing a warning for this is that it's not undefined behavior according to the standard. If you convert a signed value to an unsigned type of the same size (or larger), you can later convert that back to a signed value of the original signed type and get the original value1 on any standards-compliant compiler.

    In addition, using negative values converted to size_t is fairly common practice for various error conditions -- many system calls return an unsigned (size_t or off_t) value for success or a -1 (converted to unsigned) for an error. So adding such a warning to the compiler would cause spurious warnings for much existing code. POSIX attempts to codify this with ssize_t, but that breaks calls that may be successful with a return value greater than the maximum signed value for ssize_t.


    1"original value" here actually means "a bit pattern that compares as equal to the original bit pattern when compared as that signed type" -- padding bits might not be preserved, and if the signed representation has redundant encodings (eg, -0 and +0 in a sign-magnitude representation) it might be 'canonicalized'