Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What should happen to the negation of a size_t (i.e. `-sizeof(struct foo)`))?

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"?

like image 999
Phil Miller Avatar asked Aug 12 '09 22:08

Phil Miller


People also ask

Can a size_t be negative?

The size_t data type is never negative.

What is the sizeof size_t?

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.

Is size_t unsigned or signed?

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.

What is the value of size_t?

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.


2 Answers

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.

like image 119
Pavel Minaev Avatar answered Oct 14 '22 01:10

Pavel Minaev


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.

like image 2
John Millikin Avatar answered Oct 14 '22 01:10

John Millikin