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

G

Guest

----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.
 
E

Eric Sosman

No said:
#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.
 
G

Guest

No said:
#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.
 
D

Dietmar Schindler

No said:
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).
 
L

Lawrence Kirby

.


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
 
M

Micah Cowan

Lawrence said:
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...)
 
E

Eric Sosman

Micah said:
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'.
 
M

Micah Cowan

Eric said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top