I'm dealing with some code at work that includes an expression of the form
-(sizeof(struct foo))
i.e. the negation of a size_t
, and I'm unclear on what the C and C++ standards require of compilers when they see this. Specifically, from looking around here and elsewhere, sizeof
returns an unsigned integral value of type size_t
. I can't find any clear reference for specified behavior when negating an unsigned integer. Is there any, and if so, what is it?
Edit: Ok, so there are some good answers regarding arithmetic on unsigned types, but it's not clear that this is in fact such. When this negates, is it operating on an unsigned integer, or converting to a signed type and doing something with that? Is the behavior to expect from the standards "imagine it's the negative number of similar magnitude and then apply the 'overflow' rules for unsigned values"?
The size_t data type is never negative.
size_t type is a base unsigned integer type of C/C++ language. It is the type of the result returned by sizeof operator. The type's size is chosen so that it can store the maximum size of a theoretically possible array of any type. On a 32-bit system size_t will take 32 bits, on a 64-bit one 64 bits.
size_t is the unsigned integer type of the result of sizeof , _Alignof (since C11) and offsetof, depending on the data model. The bit width of size_t is not less than 16.
size_t is an unsigned type according to the standard. So say it's defined as a 32-bit value. A -1 is represented as 0xffffffff for a signed value using two's complement.
Both ISO C and ISO C++ standards guarantee that unsigned arithmetic is modulo 2n - i.e., for any overflow or underflow, it "wraps around". For ISO C++, this is 3.9.1[basic.fundamental]/4:
Unsigned integers, declared
unsigned
, shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.41...
41) This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type.
For ISO C(99), it is 6.2.5/9:
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
Which means the result is guaranteed to be the same as SIZE_MAX - (sizeof(struct foo)) + 1
.
In ISO 14882:2003 5.3.1.7:
[...] The negative of an unsigned quantity is computed by subtracting its value from 2n, where n is the number of bits in the pro- moted operand. The type of the result is the type of the promoted operand.
http://msdn.microsoft.com/en-us/library/wxxx8d2t%28VS.80%29.aspx
Unary negation of unsigned quantities is performed by subtracting the value of the operand from 2n, where n is the number of bits in an object of the given unsigned type. (Microsoft C++ runs on processors that utilize two's-complement arithmetic. On other processors, the algorithm for negation can differ.)
In other words, the exact behavior will be architecture-specific. If I were you, I would avoid using such a weird construct.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With