This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

0x80000000 or 0xFFFFFFFF

Hi community,

 

I deal with TMS320C28x and want to ask what the compiler does when having the following code:

long long_A = 1000L;

....

if (long_A == 0x80000000)

...

 

What does the compiler do with long_A in the comparison? To which data type is it castet?

Are there rules which tell you what the compiler does with 0x80000000 or 0xFFFFFFFF.

Is it interpreted as -2147483648 and -1?

 

I appreciate your help,

JD

  • 0x80000000 and 0xFFFFFFFF are both interpreted as "unsigned long int."  This behavior is dictated by the C standard and by the sizes of the types in the implementation.  There is a table in the C standard ("Integer Constants" C89: 3.1.3.2, C90: 6.1.3.2, C99: 6.4.4.1) which describes the types to try, in order.  The order is determined solely by whether it is decimal or hexadecimal and whether it has a type suffix.  The context in which it appears is irrelevant.

    Your example compares the variable long_A, of type "long", to 0x80000000, which is of type "unsigned long".  As required by the usual arithmetic conversions, the "long" value gets converted to "unsigned long" before comparison.  As a rule of thumb, when the operands' types have the same size, but one is unsigned, the signed one gets converted to an unsigned type.  ("Usual Arithmetic Conversions" C89: 3.2.1.5, C90: 6.2.1.5, C99: 6.3.1.8)

    If the type of "long_A" had been "long long", the constant 0x80000000 would have been promoted by the usual arithmetic conversions to "long long" before being compared to "long_A", since the size of "long long int" is bigger than "unsigned long int".  The resulting value of the conversion would be 2147483648.   (0xFFFFFFFF would become 4294967295.)

    If you want to ensure that the constant is treated as a signed long int, you need to add a 'L' suffix to the constant, like "0x80000000L".

    [Edit: the type of "long_A" is actually "long" -- Archaeologist ]

    [Edit: added C standard section cites, and 'L' does not ensure signed type.  --Archaeologist ]

  • In my previous post, I mistakenly read the type of the variable "long_A" as "long long".  The actual type is "long."  I will revise my previous post to correct the mistake, which alters how the types get promoted.

  • Hi Archaeologist,


    I have debugged the code and entering the value 0x80000000 in the debug watch window the data type is presented as long long,

    and the decimal value is displayed as 2147483648.

    It is irritating to your statement.

     

    Kind regards,

    JD

  • Hi Archaeologist,

    reading the standard it says that 0x80000000 is tried to fit in int, then in unsigned int, thenin long int. Indeed this is the case.

    So why is it converted to unsigned long?


    So having the constant 0x80000000 the value is interpreted as -2147483648?

     

    Regards,

    JD

     

  • I apologize, I forgot that the table is slightly different in C89 versus C99.  Yes, C89 says that the list for "unsuffixed octal or hexadecimal" starts with "int," which 0x80000000 does fit into, making the value -2147483648.  The TI compiler follows the C89 standard, not the C99 standard.

    [Edit: yes, the tables are slightly different, but that difference is irrelevant to this discussion.  0x80000000 does not fit into "long int", as its value (which is checked before assigning the type) is 2147483648, as explained in a later post.]

  • Thanks. Can you please still have a statement on what is happening in the debugger.

    There, 0x80000000 is displayed as long long value and the decimal value is 2147483648.

    Any idea?

    JD

  • I believe that is a bug in the debugger, but I am not an expert on the debugger. What version of the debugger are you using?  I've submitted SDSCM00035598 for further analysis and tracking.

  • Once again, my haste has led me to make an error.  0x80000000 will not fit into "int" on C28x, which is only 16 bits.  We have to go through the rest of the list, which reads in full "int, unsigned int, long int, unsigned long int."  The first type into which it fits is "long int."  I'll take some time to double-check everything and edit my earlier posts.

    [Edit: doubly wrong because 0x80000000 is actually unsigned long.  See the earlier posts.  --Archaeologist]

  • Let me summarize:

    0x80000000 is interpreted as long int, the value is -2147483648.

    0xFFFFFFFF is interpreted as long int, the value is -1.

    Having a statement like

    if (lA == 0x800000000) /* data type of lA is long int*/

    no cast is performed, as both data types are long int.

    Moreover, debugging in CodeComposerStudio is irritating as

    the wrong data type and value is diplayed for 0x80000000 (long long 2147483648).

    Obviously, the debugger has a bug.

    I myselft use CodeComposerStudio 3.3


    JD

  • Hi !

    Can you please verify my summary?

    Thanks,

    JD

  • I'm sorry I have been unable to respond earlier, as I've been ill and unable to spend time thinking about this issue.  Perhaps I can blame the illness for the several mistakes I've made.

    The latest mistake is that I posted an incorrect correction.  The truth is that 0x80000000 has unsigned long type.  I'll go back and edit my post where I made the incorrect correction.

    The value of a constant is determined before its type.  That is, the value of 0x80000000 is 2147483648.  It is this value which is consulted when looking through the table, and this value will not fit into a signed long.  Thus, the type of 0x80000000 is determined as unsigned long, the first type in which the value can be correctly represented.  Similarly, 0xFFFFFFFF has value 4294967295, and is also an unsigned long.

    I've attached a test case to demonstrate that this is the way the compiler is doing it.

    Julian Dieterle said:
    if (lA == 0x800000000) /* data type of lA is long int*/

    no cast is performed, as both data types are long int.

    0x80000000 is unsigned long, so lA is converted to unsigned long before the comparison.

    Regardless, at no time should "long long" or "unsigned long long" enter into the picture.

    Julian Dieterle said:

    Moreover, debugging in CodeComposerStudio is irritating as

    the wrong data type and value is diplayed for 0x80000000 (long long 2147483648).

    Obviously, the debugger has a bug.

    Well, it seems to me that this is a bug in the debugger (SDSCM00035598).  My rationale would be that the debugger should follow the rules of the C standard as applied the target-specific type sizes in the implementation, and assign the same type that the C compiler would.  However, it's not absolutely clear to me that that's the rule the debugger should be following, and I'll let someone from that team address that issue.

    [Edit: small enhancement to test case, also fixed a minor issue with negate. --Archaeologist ]

  • Hi Archaeologist,

     

    it is good to hear that you are back again.

    Thanks for your explanation. I have added an attachment which shows what CC Studio makes wrong.

     

    Thanks again!

    JD