EmbeddedRelated.com
Forums

IAR weird signed long long behavior

Started by Gabriel July 20, 2006
--- In m..., Joe Radomski wrote:
>
> >double f;
> >f = 2/3;
> >assigning 0.9 to f.
>
>
> Please expand on this...

OOPS, that should be

assigning 0.0 to f

of course

Robert

Beginning Microcontrollers with the MSP430

--- In m..., Gabriel Calin wrote:
> ... I always thought C compilers automatically widen constants,
> var, etc, to the largest type in the expression, unless you
> explicit cast them with a different type. Isn't it right? ...

It is like playing a chess game. When you lose a game, it shows how
smart your opponent is and how dumb you are. Your opponent is not
there to help you; he is there to defeat you.

Volatile long long myvar;
myvar = +2147483647; //This stores 0x000000007FFFFFFF in myvar.
myvar = -2147483647; //This stores 0xFFFFFFFF80000001 in myvar.
myvar = +9999999999; //This stores 0x00000002540BE3FF in myvar.
myvar = -9999999999; //This stores 0xFFFFFFFDABF41C01 in myvar.

Very good game so far.

myvar = +2147483648; //This stores 0x0000000080000000 in myvar.
myvar = -2147483648; //This stores 0x0000000080000000 in myvar too!

Surprise! You loss. See how smart the compiler is?

Thanks..

You had me confused there for a second.. makes sense now

robertadsett wrote:
--- In m..., Joe Radomski wrote:
>
> >double f;
> >f = 2/3;
> >assigning 0.9 to f.
> Please expand on this...

OOPS, that should be

assigning 0.0 to f

of course

Robert



Really nice example :) But strictly Ansi-C speaking, when I use signed
int and signed long (at least in other compilers) I never had to worry
about storing a -1 in a signed int and the compiler generate code to
store 0x0080 instead of 0x8000. Same to signed long. Shouldn't it be the
same case for signed long long? It seen you would have to add the proper
suffix on every single constant in you code or the compiler would use
the smallest type possible to fit the number, possible violating the
variables size.

gcalin

old_cow_yellow wrote:
>
> --- In m... ,
> Gabriel Calin wrote:
> > ... I always thought C compilers automatically widen constants,
> > var, etc, to the largest type in the expression, unless you
> > explicit cast them with a different type. Isn't it right? ...
>
> It is like playing a chess game. When you lose a game, it shows how
> smart your opponent is and how dumb you are. Your opponent is not
> there to help you; he is there to defeat you.
>
> Volatile long long myvar;
> myvar = +2147483647; //This stores 0x000000007FFFFFFF in myvar.
> myvar = -2147483647; //This stores 0xFFFFFFFF80000001 in myvar.
> myvar = +9999999999; //This stores 0x00000002540BE3FF in myvar.
> myvar = -9999999999; //This stores 0xFFFFFFFDABF41C01 in myvar.
>
> Very good game so far.
>
> myvar = +2147483648; //This stores 0x0000000080000000 in myvar.
> myvar = -2147483648; //This stores 0x0000000080000000 in myvar too!
>
> Surprise! You loss. See how smart the compiler is?
>
>



--- In m..., Gabriel Calin wrote:
>
> Really nice example :) But strictly Ansi-C speaking, when I use signed
> int and signed long (at least in other compilers) I never had to worry
> about storing a -1 in a signed int and the compiler generate code to
> store 0x0080 instead of 0x8000. Same to signed long. Shouldn't it be
the
> same case for signed long long? It seen you would have to add the
proper
> suffix on every single constant in you code or the compiler would use
> the smallest type possible to fit the number, possible violating the
> variables size.

If you store a -1 that's true. The -1 is an int and when assigned to
a long or long long gets appropriately sign extended. If assigned to a
char it gets appropriately truncated. BTW 0x8000 != -1, 0xFFFF == -1

On a system with 16 bit ints given

int x;

x = 32769;

The compiler has two options
- Convert 32769 to some int value silently
- Convert 32769 to some int value and warn the user that 32769
doesn't fit into an int.

In neither case will you have an internal representation of 32769.

Given

long x;

x = 32769;

The compiler has two options
- Convert 32769 to some int value silently
- Convert 32769 to some int value and warn the user that 32769
doesn't fit into an int.

The compiler can then sign extend the int to a long and assign it to
x. You will still never have an internal representation of 32769.

Given

long x;

x = 32769L;

Now the compiler is allowed to use an internal representation of a
long and assign 32769 to x.

A compiler that does otherwise is broken.

Robert

--- In m..., "robertadsett"
wrote:
> ......
> Given
>
> long x;
>
> x = 32769;
>
> The compiler has two options
> - Convert 32769 to some int value silently
> - Convert 32769 to some int value and warn the user that 32769
> doesn't fit into an int.
>
> The compiler can then sign extend the int to a long and assign it to
> x. You will still never have an internal representation of 32769.
> ......

Well. The IAR MSP430 compiler does it differently. In the above case,
x does get the value 0x00008001, which is decimal 32769.

When the left-hand-side is a signed long and the right-hand-side is a
number between 2147483647 and -2147483648 inclusive, IAR generates
the correct internal representation automatically. I think this
is "nice". Is it "illegal" for the compiler to do so?

When the number is outside of the above said range, depend on the
value of the number, IAR sometime warns you, but sometime it does
not. To warn or not to warn, they are both "legal". But I think this
inconsistency is not very "nice".

As shown in my previous msg in this thread, when the left-hand-side
is a signed long long, and right-hand-side is a number between
9223372036854775807 and 9223372036854775808, IAR generates the
correct internal representation correctly 99.999% of the time and
generates an incorrect representation ~0.001% of the time.

Is IAR "illegal" 99.999% of the time and "legal" ~0.001% of the time?
I think it is "nice" 99.999% of the time but the ~0.001% is
really "nasty"!

I know I know. One should always type-case numbers that is not int.
The compiler may appear to be very nice and very friendly. But do not
let it fool you, if you let your guards down, bang you are
dead. "He is not there to help you, he is there to defeat you".





I tried replying earlier, but my ISP went down hard. Still not
completely recovered.

--- In m..., "old_cow_yellow"
wrote:
>
> --- In m..., "robertadsett"
> wrote:
> > ......
> > Given
> >
> > long x;
> >
> > x = 32769;
> >
> > The compiler has two options
> > - Convert 32769 to some int value silently
> > - Convert 32769 to some int value and warn the user that 32769
> > doesn't fit into an int.
> >
> > The compiler can then sign extend the int to a long and assign it to
> > x. You will still never have an internal representation of 32769.
> > ......
>
> Well. The IAR MSP430 compiler does it differently. In the above case,
> x does get the value 0x00008001, which is decimal 32769.
>
> When the left-hand-side is a signed long and the right-hand-side is a
> number between 2147483647 and -2147483648 inclusive, IAR generates
> the correct internal representation automatically. I think this
> is "nice". Is it "illegal" for the compiler to do so?

I believe so, yes. They might be able to argue that the behaviour is
undefined and they can do anything they wish. But I believe that the
situation is as I described, the number is an integer and must behave
as one with the approriate sign extension on conversion to a long. I
think the only leeway they have is what integer they will produce
before the conversion to long (and 0x8001 is signed and therefore
should be sign extended). I suspect they are checking the sign of a
compiler internal 32 bit number when determining whether to sign
extend rather than the micro's 16 bit representation.

Since the 16 bit number that is being sign extended into a long is not
defined I don't think it's possible to come up with code that depends
on the 'correct' interpretation. Any code that works the way you want
is working accidentally and is subect to very different behaviour with
a different compiler or even different versions of the same compiler.

As failures go it's pretty minor but it does give people surprises.
It really is pretty hard to make the case that they are producing the
wrong broken code :)
> not. To warn or not to warn, they are both "legal". But I think this
> inconsistency is not very "nice".

It's a quality of implementation issue. Frankly I don't rely on
compilers for this sort of thing. They just aren't optimized for it.
A good static code checker like PC-Lint is much better.

> I know I know. One should always type-case numbers that is not int.

Not should, must. Anything else is not legal code.

> The compiler may appear to be very nice and very friendly. But do not
> let it fool you, if you let your guards down, bang you are
> dead. "He is not there to help you, he is there to defeat you".

Nonsense. The compiler is an interpreter of instructions not an
adversary. The better phrase (not my own) is "If you lie to the
compiler it will get its revenge."

Robert