Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Help with Constant Define--Compiler Issue with ANSI or my compiler or me? (http://www.velocityreviews.com/forums/t436315-help-with-constant-define-compiler-issue-with-ansi-or-my-compiler-or-me.html)

No Spam 12-29-2004 09:32 AM

Help with Constant Define--Compiler Issue with ANSI or my compiler or me?
 


----snip

#define POSITIVE_INTEGRATOR_SATURATION 0x03000000L //
#define NEGATIVE_INTEGRATOR_SATURATION 0xFD000000L //



long integrator;

integrator=0;

if (integrator>POSITIVE_INTEGRATOR_SATURATION)
integrator=POSITIVE_INTEGRATOR_SATURATION;
if (integrator<NEGATIVE_INTEGRATOR_SATURATION)
integrator=NEGATIVE_INTEGRATOR_SATURATION;


1. Why does the executable always assign
NEGATIVE_INTEGRATOR_SATURATION to integrator?

-I assume that long declaration means the value is signed (the most
significant bit indicates sign)

------------
#define INTEGRATOR_SATURATION 0x03000000L // 3



long integrator;

integrator=0;

if (integrator>INTEGRATOR_SATURATION)
integrator=POSITIVE_INTEGRATOR_SATURATION;
if (integrator<(0-INTEGRATOR_SATURATION))
integrator=NEGATIVE_INTEGRATOR_SATURATION;

This code leaves integrator at 0, as intended.

-------------

2. Why does the second snippet work, while the first does not.

Additional Info- My machine uses four bytes for long.

I would be happy to learn how to make this portable as soon as I stop
the limit cycles in my control system.





Eric Sosman 12-29-2004 01:50 PM

Re: Help with Constant Define--Compiler Issue with ANSI or my compileror me?
 
No Spam wrote:

> #define POSITIVE_INTEGRATOR_SATURATION 0x03000000L //
> #define NEGATIVE_INTEGRATOR_SATURATION 0xFD000000L //
>
> long integrator;
>
> integrator=0;
>
> if (integrator>POSITIVE_INTEGRATOR_SATURATION)
> integrator=POSITIVE_INTEGRATOR_SATURATION;
> if (integrator<NEGATIVE_INTEGRATOR_SATURATION)
> integrator=NEGATIVE_INTEGRATOR_SATURATION;
>
> 1. Why does the executable always assign
> NEGATIVE_INTEGRATOR_SATURATION to integrator?


Because NEG...ION is a large positive number, hence
greater than zero.

> -I assume that long declaration means the value is signed (the most
> significant bit indicates sign)


Yes, a `long' is signed. And yes, the most significant
bit of a signed integer is the sign bit. But you've missed
something: The type of 0xFD000000L is not `long' (on your
machine, where `long' occupies 32 bits), but `unsigned long'.
Section 6.4.4.1 paragraph 5:

The type of an integer constant is the first of the
corresponding list in which its value can be
represented.
[... and for a hexadecimal constant with an L suffix
the list begins `long int', `unsigned long int', ...]

Since the value 0xFD000000L (4244635648) is greater than
your system's LONG_MAX, it cannot be represented as a `long'.
But it can be represented as an `unsigned long', so that is
the constant's type.

Now: Almost all C operators that use two operands require
the operands to have the same type. If they're not already
of the same type, C promotes one or both until the promoted
types match, and then applies the operator to the promoted
values. When you write

integrator < NEG...ION

you are trying to compare a `long' and an `unsigned long',
so C actually evaluates

(unsigned long)integrator < NEG...ION

.... and for the values given, this comparison is true.

Suggested fix:

#define NEG...ION -0x30000000L

Inferior (because of dubious portability) fix:

#define NEG...ION (long)0xFD000000

General principle: Stop thinking about the way your numbers
are represented, and start thinking about their values. You
will save yourself much frustration by doing so.

--
Eric Sosman
esosman@acm-dot-org.invalid

No Spam 12-29-2004 08:58 PM

Re: Help with Constant Define--Compiler Issue with ANSI or my compiler or me?
 
On Wed, 29 Dec 2004 08:50:46 -0500, Eric Sosman
<esosman@acm-dot-org.invalid> wrote:

>No Spam wrote:
>
>> #define POSITIVE_INTEGRATOR_SATURATION 0x03000000L //
>> #define NEGATIVE_INTEGRATOR_SATURATION 0xFD000000L //
>>
>> long integrator;
>>
>> integrator=0;
>>
>> if (integrator>POSITIVE_INTEGRATOR_SATURATION)
>> integrator=POSITIVE_INTEGRATOR_SATURATION;
>> if (integrator<NEGATIVE_INTEGRATOR_SATURATION)
>> integrator=NEGATIVE_INTEGRATOR_SATURATION;
>>
>> 1. Why does the executable always assign
>> NEGATIVE_INTEGRATOR_SATURATION to integrator?

>
> Because NEG...ION is a large positive number, hence
>greater than zero.
>
>> -I assume that long declaration means the value is signed (the most
>> significant bit indicates sign)

>
> Yes, a `long' is signed. And yes, the most significant
>bit of a signed integer is the sign bit. But you've missed
>something: The type of 0xFD000000L is not `long' (on your
>machine, where `long' occupies 32 bits), but `unsigned long'.
>Section 6.4.4.1 paragraph 5:
>
> The type of an integer constant is the first of the
> corresponding list in which its value can be
> represented.
> [... and for a hexadecimal constant with an L suffix
> the list begins `long int', `unsigned long int', ...]


> Since the value 0xFD000000L (4244635648) is greater than
>your system's LONG_MAX, it cannot be represented as a `long'.
>But it can be represented as an `unsigned long', so that is
>the constant's type.


You are telling me

#define foo1 0xFFFFFFFFL

#define foo2 -1L

(foo1==foo2) evaluates to false

where the machine allocates 32 bits for type long?

Correct?

So by the paragraph,


#define foo1 0xFFFFFFFFUL

#define foo2 0xFFFFFFFFL

(foo1==foo2) evaluates to true (on my machine)?


> Now: Almost all C operators that use two operands require
>the operands to have the same type. If they're not already
>of the same type, C promotes one or both until the promoted
>types match, and then applies the operator to the promoted
>values. When you write
>
> integrator < NEG...ION
>
>you are trying to compare a `long' and an `unsigned long',
>so C actually evaluates
>
> (unsigned long)integrator < NEG...ION
>
>... and for the values given, this comparison is true.
>
> Suggested fix:
>
> #define NEG...ION -0x30000000L
>
> Inferior (because of dubious portability) fix:
>
> #define NEG...ION (long)0xFD000000
>
> General principle: Stop thinking about the way your numbers
>are represented, and start thinking about their values. You
>will save yourself much frustration by doing so.


Yes I freely admit that I translated the code into C from an assembly
program, but kept the assembly language way of thinking. Plus I never
would have thought of expressing a hexadecimal number with a negative
sign in front of it.

Dietmar Schindler 12-30-2004 10:56 AM

Re: Help with Constant Define--Compiler Issue with ANSI or my compiler or me?
 
No Spam wrote:
> You are telling me
>
> #define foo1 0xFFFFFFFFL
>
> #define foo2 -1L
>
> (foo1==foo2) evaluates to false
>
> where the machine allocates 32 bits for type long?


Let me say that he is not telling you that. For the equality operation,
the (long) operand -1L is converted to the type of the (unsigned long)
operand 0xFFFFFFFFL. Consequently, the expression evaluates to 1 (true).

Lawrence Kirby 12-30-2004 01:09 PM

Re: Help with Constant Define--Compiler Issue with ANSI or my compiler or me?
 
On Wed, 29 Dec 2004 20:58:42 +0000, No Spam wrote:

> On Wed, 29 Dec 2004 08:50:46 -0500, Eric Sosman>
> <esosman@acm-dot-org.invalid> wrote:


....

>> Since the value 0xFD000000L (4244635648) is greater than
>>your system's LONG_MAX, it cannot be represented as a `long'.
>>But it can be represented as an `unsigned long', so that is
>>the constant's type.

>
> You are telling me
>
> #define foo1 0xFFFFFFFFL
>
> #define foo2 -1L
>
> (foo1==foo2) evaluates to false
>
> where the machine allocates 32 bits for type long?
>
> Correct?


No, on an implementation with 32 bit longs Eric is saying that 0XFFFFFFFFL
will have type unsigned long. In the expression foo1==foo2, since the left
hand side has type unsigned long, the right hand side will be converted to
that type before the comparison is made. (unsigned long)-1L evaluates to
ULONG_MAX which in 32 bits will be 0xFFFFFFFF so foo1 and foo2 will
compare equal in that case.

> So by the paragraph,
>
>
> #define foo1 0xFFFFFFFFUL
>
> #define foo2 0xFFFFFFFFL
>
> (foo1==foo2) evaluates to true (on my machine)?


Yes, in a 32 bit type foo1 and foo2 both have type unsigned long
with the same value.

Lawrence

Micah Cowan 01-03-2005 09:45 PM

Re: Help with Constant Define--Compiler Issue with ANSI or my compileror me?
 
Lawrence Kirby wrote:
>>#define foo1 0xFFFFFFFFUL
>>
>>#define foo2 0xFFFFFFFFL
>>
>>(foo1==foo2) evaluates to true (on my machine)?

>
>
> Yes, in a 32 bit type foo1 and foo2 both have type unsigned long
> with the same value.


Actually, on an implementation with 32-bit long, 0xFFFFFFFFL
should be implementation defined, no? (i.e., it won't necessarily
get the value -1, and thus won't necessarily convert to
0xFFFFFFFFUL on comparison...)

Eric Sosman 01-03-2005 10:13 PM

Re: Help with Constant Define--Compiler Issue with ANSI or my compileror me?
 
Micah Cowan wrote:
> Lawrence Kirby wrote:
>
>>>#define foo1 0xFFFFFFFFUL
>>>
>>>#define foo2 0xFFFFFFFFL
>>>
>>>(foo1==foo2) evaluates to true (on my machine)?

>>
>>
>>Yes, in a 32 bit type foo1 and foo2 both have type unsigned long
>>with the same value.

>
>
> Actually, on an implementation with 32-bit long, 0xFFFFFFFFL
> should be implementation defined, no? (i.e., it won't necessarily
> get the value -1, and thus won't necessarily convert to
> 0xFFFFFFFFUL on comparison...)


Aside from the 32-bitness of `long' there's nothing
implementation-defined about it. The constant's value is
too large for `long', so its type will be `unsigned long'
and its value will be 4294967295UL or `(unsigned long)-1'.

--
Eric.Sosman@sun.com


Micah Cowan 01-04-2005 01:37 AM

Re: Help with Constant Define--Compiler Issue with ANSI or my compileror me?
 
Eric Sosman wrote:
> Micah Cowan wrote:


> Aside from the 32-bitness of `long' there's nothing
> implementation-defined about it. The constant's value is
> too large for `long', so its type will be `unsigned long'
> and its value will be 4294967295UL or `(unsigned long)-1'.
>


Oops. Yup. I shoulda known better than to correct a message from
Lawrence.


All times are GMT. The time now is 07:11 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.