473,324 Members | 2,193 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,324 software developers and data experts.

Semantics of unary minus

Hi,

I've been lurking on clc for a few months now, and want to start by
thanking the regulars here for opening my eyes to a whole new dimension
of "knowing c". Considering I had never even touched the standards a
year ago, though I graduated in embedded SW development...

Anyway, to the problem at hand: I've stumbled upon the following
construct at work recently, and cannot really make up my mind about the
standard's take on the matter.

int a;
unsigned int b;

if(a < 0) {
b = -a;
}

I just can't decide if this is valid when a's value is -32768 (admitting
16 bit ints). I can't see how the standard's wording on unary minus
semantics allows for 2's complement asymmetry. C99 says:

"The result of the unary - operator is the negative of its (promoted)
operand. The integer promotions are performed on the operand, and the
result has the promoted type." (I'm also slightly suspicious about the
disappearance of "value" as compared to the semantics of unary plus...)

Unless I'm mistaken, a won't be promoted (being an int), so there might
be no such thing as "the negative of its (promoted) operand"? I feel
like the standard tells me I might end up with an int worth 32768...
(still assuming 16 bit ints)? Or should I consider there is an implied
"if-it-fits-otherwise-overflow"?

I couldn't find any help through google or in the FAQ, so I'd really
appreciate any clarification.

Marc
Feb 12 '06 #1
13 5058
"Marc" <no****@mail.com> wrote in message
news:ds*************@news.t-online.com...
int a;
unsigned int b;

if(a < 0) {
b = -a;
}

I just can't decide if this is valid when a's value is -32768 (admitting
16 bit ints). I can't see how the standard's wording on unary minus
semantics allows for 2's complement asymmetry. C99 says:


-a overflows and typically yields -32768 without a trap
(though an implementation doesn't have to). The conversion
is 2^16 - 32768, which is 32768. So you luck out.

Converting to unsigned long doesn't work quite as well.
It is much safer to write "b = 0U - a" instead.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Feb 12 '06 #2
Marc wrote:
Hi,

I've been lurking on clc for a few months now, and want to start by
thanking the regulars here for opening my eyes to a whole new dimension
of "knowing c". Considering I had never even touched the standards a
year ago, though I graduated in embedded SW development...

Anyway, to the problem at hand: I've stumbled upon the following
construct at work recently, and cannot really make up my mind about the
standard's take on the matter.

int a;
unsigned int b;

if(a < 0) {
b = -a;
}

I just can't decide if this is valid when a's value is -32768 (admitting
16 bit ints). I can't see how the standard's wording on unary minus
semantics allows for 2's complement asymmetry. C99 says:

"The result of the unary - operator is the negative of its (promoted)
operand. The integer promotions are performed on the operand, and the
result has the promoted type." (I'm also slightly suspicious about the
disappearance of "value" as compared to the semantics of unary plus...)

Unless I'm mistaken, a won't be promoted (being an int), so there might
be no such thing as "the negative of its (promoted) operand"? I feel
like the standard tells me I might end up with an int worth 32768...
(still assuming 16 bit ints)? Or should I consider there is an implied
"if-it-fits-otherwise-overflow"?

I couldn't find any help through google or in the FAQ, so I'd really
appreciate any clarification.


Yes, two's complement is asymmetric about zero: there
is a negative number whose absolute value is not representable.
(The Standard actually permits an implementation to dodge this
asymmetry by defining "all ones" to be a trap representation;
I've never heard of an implementation that does so.)

However, that doesn't mean unary minus is undefined: it's
only undefined if its operand has an inappropriate value. This
is really no different from the situation with binary minus:

"The result of the binary - operator is the difference
resulting from the subtraction of the second operand
from the first." (6.5.6/6)

This is not to be taken as implying that all subtractions must
produce mathematically correct results: `INT_MIN - 42', for
example, is clearly not going to produce a value less than
INT_MIN.

When this sort of thing happens, another provision of the
Standard takes over:

"If an _exceptional condition_ occurs during the
evaluation of an expression (that is, if the result
is not mathematically defined or not in the range of
representable values for its type), the behavior is
undefined." (6.5/5)

So: If you try to negate (or take the absolute value of)
INT_MIN on a system where `INT_MIN + INT_MAX' is not zero, the
C language does not specify the outcome -- anything can happen,
at least in principle. The commonest behavior is that the
overflow is ignored, and the resulting representation (all ones)
is equal to INT_MIN again: INT_MIN is its own negation on most
two's-complement systems. However, this should be thought of
as a quirk of those systems, not as part of the C language.

--
Eric Sosman
es*****@acm-dot-org.invalid
Feb 12 '06 #3
Marc wrote:
int a; -a; "if-it-fits-otherwise-overflow"?


Yes.
"overflow" as in "undefined behavior".

It's a point of trivia which also comes up when writing itoa,
that there is no integer type which is guaranteed
to be able to represent the magnitude of INT_MIN.

--
pete
Feb 12 '06 #4

"Marc" <no****@mail.com> wrote in message
news:ds*************@news.t-online.com...
Hi,

I've been lurking on clc for a few months now, and want to start by
thanking the regulars here for opening my eyes to a whole new dimension
of "knowing c". Considering I had never even touched the standards a
year ago, though I graduated in embedded SW development...

Anyway, to the problem at hand: I've stumbled upon the following
construct at work recently, and cannot really make up my mind about the
standard's take on the matter.

int a;
unsigned int b;

if(a < 0) {
b = -a;
}

I just can't decide if this is valid when a's value is -32768 (admitting
16 bit ints). I can't see how the standard's wording on unary minus
semantics allows for 2's complement asymmetry. C99 says:

"The result of the unary - operator is the negative of its (promoted)
operand. The integer promotions are performed on the operand, and the
result has the promoted type." (I'm also slightly suspicious about the
disappearance of "value" as compared to the semantics of unary plus...)

Unless I'm mistaken, a won't be promoted (being an int), so there might
be no such thing as "the negative of its (promoted) operand"? I feel
like the standard tells me I might end up with an int worth 32768...
(still assuming 16 bit ints)? Or should I consider there is an implied
"if-it-fits-otherwise-overflow"?

I couldn't find any help through google or in the FAQ, so I'd really
appreciate any clarification.


I'm not going to help you comprehend the spec. There are a few other people
here better at that than me. But, I can tell how the 16-bit and 32-bit
compilers that I use work in this area. The 16-bit compilers will not
convert -32768. It remains negative. But, they will convert -32767 (to -1)
to +32767 (to +1). The 32-bit compilers convert -32768 to +32768.
Basically, if it won't fit into the converted type, it doesn't get
converted.
Rod Pemberton

Feb 12 '06 #5
pete wrote:

Marc wrote:
int a;

-a;

"if-it-fits-otherwise-overflow"?


Yes.
"overflow" as in "undefined behavior".

It's a point of trivia which also comes up when writing itoa,
that there is no integer type which is guaranteed
to be able to represent the magnitude of INT_MIN.


You can see what INT_MIN expands to on your implementation.
It might be something like (-32767 - 1),
if you have two's complement representation of negative integers.

/* BEGIN new.c */

#include <stdio.h>
#include <limits.h>

#define str(s) # s
#define xstr(s) str(s)

int main(void)
{
puts("INT_MIN is " xstr(INT_MIN));
return 0;
}

/* END new.c */

--
pete
Feb 12 '06 #6
Eric Sosman wrote:
[...]
When this sort of thing happens, another provision of the
Standard takes over:

"If an _exceptional condition_ occurs during the
evaluation of an expression (that is, if the result
is not mathematically defined or not in the range of
representable values for its type), the behavior is
undefined." (6.5/5)

So: If you try to negate (or take the absolute value of)
INT_MIN on a system where `INT_MIN + INT_MAX' is not zero, the
C language does not specify the outcome -- anything can happen,
at least in principle. The commonest behavior is that the
overflow is ignored, and the resulting representation (all ones)
is equal to INT_MIN again: INT_MIN is its own negation on most
two's-complement systems. However, this should be thought of
as a quirk of those systems, not as part of the C language.


Ah yes ... 6.5/5 states exactly what I was looking for. Thanks a lot for
the pointer - guess I still have a cover-to-cover reading to do ...

As you and others suggested, the negation did work on our system, now I
know for sure it was just "lucking-out" from a standard's point of view.

Thanks all for the answers,

Marc
Feb 12 '06 #7
Eric Sosman wrote:

<snip: question about unary minus overflowing for INT_MIN>
Yes, two's complement is asymmetric about zero: there
is a negative number whose absolute value is not representable.
(The Standard actually permits an implementation to dodge this
asymmetry by defining "all ones" to be a trap representation;
I've never heard of an implementation that does so.)


ITYM a 1 followed by all 0s. All ones is -1 in two's complement.

Feb 13 '06 #8
Antonio Contreras wrote:

Eric Sosman wrote:

<snip: question about unary minus overflowing for INT_MIN>
Yes, two's complement is asymmetric about zero: there
is a negative number whose absolute value is not representable.
(The Standard actually permits an implementation to dodge this
asymmetry by defining "all ones" to be a trap representation;
I've never heard of an implementation that does so.)


ITYM a 1 followed by all 0s. All ones is -1 in two's complement.


He's talking about negative zero.
A one followed by all zeros, is negative zero
in sign and magnitude representation.
All ones is negative zero in one's complement representation.
There's different ways for an implementation
to deal with negative zero, trapping is one of them.

--
pete
Feb 13 '06 #9
pete wrote:
Antonio Contreras wrote:

Eric Sosman wrote:

<snip: question about unary minus overflowing for INT_MIN>
Yes, two's complement is asymmetric about zero: there
is a negative number whose absolute value is not representable.
(The Standard actually permits an implementation to dodge this
asymmetry by defining "all ones" to be a trap representation;
I've never heard of an implementation that does so.)


ITYM a 1 followed by all 0s. All ones is -1 in two's complement.


He's talking about negative zero.
A one followed by all zeros, is negative zero
in sign and magnitude representation.
All ones is negative zero in one's complement representation.
There's different ways for an implementation
to deal with negative zero, trapping is one of them.


But he was talking about two's complement. And AFAIK the standard
allows a two's complement representation with trap representations. In
this case the obvious pattern for a trap representation is a 1 followed
by all 0s, which implies that INT_MIN = - INT_MAX

Feb 13 '06 #10
Antonio Contreras wrote:

pete wrote:
Antonio Contreras wrote:

Eric Sosman wrote:

<snip: question about unary minus overflowing for INT_MIN>

> Yes, two's complement is asymmetric about zero: there
> is a negative number whose absolute value is not representable.
> (The Standard actually permits an implementation to dodge this
> asymmetry by defining "all ones" to be a trap representation;
> I've never heard of an implementation that does so.)

ITYM a 1 followed by all 0s. All ones is -1 in two's complement.


He's talking about negative zero.
A one followed by all zeros, is negative zero
in sign and magnitude representation.
All ones is negative zero in one's complement representation.
There's different ways for an implementation
to deal with negative zero, trapping is one of them.


But he was talking about two's complement. And AFAIK the standard
allows a two's complement representation with trap representations. In
this case the obvious pattern
for a trap representation is a 1 followed
by all 0s, which implies that INT_MIN = - INT_MAX


Yes, I had missed the point.

--
pete
Feb 13 '06 #11
On 2006-02-12, pete <pf*****@mindspring.com> wrote:
Marc wrote:
int a;

-a;

"if-it-fits-otherwise-overflow"?


Yes.
"overflow" as in "undefined behavior".

It's a point of trivia which also comes up when writing itoa,
that there is no integer type which is guaranteed
to be able to represent the magnitude of INT_MIN.


Not unsigned int?
Feb 13 '06 #12
Antonio Contreras wrote:
Eric Sosman wrote:

<snip: question about unary minus overflowing for INT_MIN>
Yes, two's complement is asymmetric about zero: there
is a negative number whose absolute value is not representable.
(The Standard actually permits an implementation to dodge this
asymmetry by defining "all ones" to be a trap representation;
I've never heard of an implementation that does so.)

ITYM a 1 followed by all 0s. All ones is -1 in two's complement.


Right you are. Sorry for the blunder.

--
Eric Sosman
es*****@acm-dot-org.invalid
Feb 13 '06 #13
Jordan Abel wrote:

On 2006-02-12, pete <pf*****@mindspring.com> wrote:
Marc wrote:
int a;

-a;

"if-it-fits-otherwise-overflow"?


Yes.
"overflow" as in "undefined behavior".

It's a point of trivia which also comes up when writing itoa,
that there is no integer type which is guaranteed
to be able to represent the magnitude of INT_MIN.


Not unsigned int?


No.
The requirement is for the unsigned type to have
at least as many value bits as the signed type.
You can have:
CHAR_BIT == 16
sizeof(int) == 2
UINT_MAX == 65535
INT_MIN == -65536
--
pete
Feb 13 '06 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Carlos Ribeiro | last post by:
I was checking the Prolog recipe in the Cookbook: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/303057 It's a clever implementation that explores some aspects of Python that I wasn't...
2
by: Dave Theese | last post by:
Am I correct in saying that it is not possible to overload unary + and unary -?
6
by: Andrew Ward | last post by:
Hi All, I tried to compile the following line: pair<long, ulong> cr3(make_pair(-2147483648L, 2147483647)); but get this error: unary minus applied to unsigned type, result still unsigned. ...
5
by: Ruben Campos | last post by:
Some questions about this code: template <typename T> class MyTemplate; template <typename T> MyTemplate <T> operator- (const MyTemplate <T> & object); template <typename T> MyTemplate <T>...
21
by: Paul Steckler | last post by:
Here's some code that's giving me differing results, depending on the compiler. typedef foo { int A,B; } FOO; int main() {
2
by: Javier Estrada | last post by:
1. For types smaller than int, when I compile: class MyClass { static void Main(string args) { x = 10; y = -x; }
6
by: Matthew Cook | last post by:
I would like to overload the unary minus operator so that I can negate an instance of a class and pass that instance to a function without creating an explicit temporary variable. Here is an...
28
by: dspfun | last post by:
I'm trying to get a good understanding of how unary operators work and have some questions about the following test snippets. int *p; ~!&*++p--; It doesn't compile, why? The problem seems to be...
16
by: JoseMariaSola | last post by:
How may operators and operands does (typename) expression has? I'd say one operator, the cast operator, and two operands: typename and expression. But everywhere I read, cast is categorized as...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.