f



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.


	

0
12/29/2004 9:32:36 AM
comp.lang.c 30657 articles. 4 followers. spinoza1111 (3246) is leader. Post Follow

7 Replies
477 Views

Similar Articles

[PageSpeed] 10

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
0
esosman (1384)
12/29/2004 1:50:46 PM
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.
0
12/29/2004 8:58:42 PM
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).
0
dSpam (87)
12/30/2004 10:56:38 AM
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
0
lknews (877)
12/30/2004 1:09:39 PM
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...)
0
micah2 (555)
1/3/2005 9:45:39 PM
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

0
Eric.Sosman (4552)
1/3/2005 10:13:12 PM
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.
0
micah2 (555)
1/4/2005 1:37:07 AM
Reply: