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

Discussion in 'C Programming' started by No Spam, Dec 29, 2004.

  1. No Spam

    No Spam 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.
    No Spam, Dec 29, 2004
    #1
    1. Advertising

  2. No Spam

    Eric Sosman Guest

    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
    lid
    Eric Sosman, Dec 29, 2004
    #2
    1. Advertising

  3. No Spam

    No Spam Guest

    On Wed, 29 Dec 2004 08:50:46 -0500, Eric Sosman
    <> 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.
    No Spam, Dec 29, 2004
    #3
  4. 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).
    Dietmar Schindler, Dec 30, 2004
    #4
  5. On Wed, 29 Dec 2004 20:58:42 +0000, No Spam wrote:

    > On Wed, 29 Dec 2004 08:50:46 -0500, Eric Sosman>
    > <> 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
    Lawrence Kirby, Dec 30, 2004
    #5
  6. No Spam

    Micah Cowan Guest

    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...)
    Micah Cowan, Jan 3, 2005
    #6
  7. No Spam

    Eric Sosman Guest

    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, Jan 3, 2005
    #7
  8. No Spam

    Micah Cowan Guest

    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.
    Micah Cowan, Jan 4, 2005
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christopher M. Lusardi
    Replies:
    1
    Views:
    4,073
  2. bilbothebagginsbab5 AT freenet DOT de
    Replies:
    31
    Views:
    1,099
    Dave Thompson
    Dec 27, 2004
  3. Replies:
    1
    Views:
    475
  4. Replies:
    11
    Views:
    1,053
    Keith Thompson
    Apr 28, 2008
  5. Frank Iannarilli

    pre-ansi to ansi c++ conversion?

    Frank Iannarilli, Jul 21, 2009, in forum: C++
    Replies:
    2
    Views:
    403
Loading...

Share This Page