cast?

Does anybody know, how one have to cast an operation correctly? And is it necessary to tell the compiler that a constant is unsined long

#define dword unsigned long
unsigned char ucH;    //hours
unsigned char ucM;    //minutes
unsigned char ucS;    //seconds
dword ulTime;         //Time in s

GetTime(...);
ulTime = ucS + ucM*60 + ucH*3600;
[..]
this won't work! How do I have to cast the calculation?

ulTime = (dword)(ucS + ucM*60 + ucH*3600);
or
ulTime = ucS + (dword)ucM*60 + (dword)ucH*3600);
or ???

I have tried to find any written description (K&R, C166-Reference) but I could't find anything about this theme!

Do I have to use 3600 or 3600ul?

Thank you
...Leo

Parents
  • #define dword unsigned long
    unsigned char ucH;    //hours
    unsigned char ucM;    //minutes
    unsigned char ucS;    //seconds
    dword ulTime;         //Time in s
    
    GetTime(...);
    ulTime = ucS + ucM*60 + ucH*3600;
    The statement you have can be rewritten using only types as:
    (ulong) = (uchar) + (uchar) * (int) + (uchar) * (int);
    Now, ANSI has very strict rules for how these operations are performed. In ANSI...
    char * int  = int
    char * long = long
    int  * long = long
    int  * int  = int
    ANSI promotion rules will fit the result of an operation to the size of the "largest" operand, but no larger (typically).

    So, Looking back at your code...
    (ulong) = (uchar) + (uchar) * (int) + (uchar) * (int);
    
       /* Is reduced to */
    
    (ulong) = (uchar) + (int) + (int);
    
       /* Which is reduced to */
    
    (ulong) = (int) + (int);
    
       /* Which is further reduced to */
    
    (ulong) = (int);
    I guess from this you are seeing a result that is REALLY not what you expected.

    The easiest solution is to change the code so that operations (+, -, *, /) are performed according to ANSI rules generating the sized results that you want. This would be the following:
    ulTime = ucS + ucM * 60UL + ucH * 3600UL;
    By changing 60 and 3600 to unsigned longs, you are changing the types of the operands. And, now, you'll get...
    (ulong) = (uchar) + (uchar) * (ulong) + (uchar) * (ulong);
    
       /* Is reduced to */
    
    (ulong) = (uchar) + (ulong) + (ulong);
    
       /* Which is reduced to */
    
    (ulong) = (ulong) + (ulong);
    
       /* Which is further reduced to */
    
    (ulong) = (ulong);
    And, that's precisely what you want.

    Jon

Reply
  • #define dword unsigned long
    unsigned char ucH;    //hours
    unsigned char ucM;    //minutes
    unsigned char ucS;    //seconds
    dword ulTime;         //Time in s
    
    GetTime(...);
    ulTime = ucS + ucM*60 + ucH*3600;
    The statement you have can be rewritten using only types as:
    (ulong) = (uchar) + (uchar) * (int) + (uchar) * (int);
    Now, ANSI has very strict rules for how these operations are performed. In ANSI...
    char * int  = int
    char * long = long
    int  * long = long
    int  * int  = int
    ANSI promotion rules will fit the result of an operation to the size of the "largest" operand, but no larger (typically).

    So, Looking back at your code...
    (ulong) = (uchar) + (uchar) * (int) + (uchar) * (int);
    
       /* Is reduced to */
    
    (ulong) = (uchar) + (int) + (int);
    
       /* Which is reduced to */
    
    (ulong) = (int) + (int);
    
       /* Which is further reduced to */
    
    (ulong) = (int);
    I guess from this you are seeing a result that is REALLY not what you expected.

    The easiest solution is to change the code so that operations (+, -, *, /) are performed according to ANSI rules generating the sized results that you want. This would be the following:
    ulTime = ucS + ucM * 60UL + ucH * 3600UL;
    By changing 60 and 3600 to unsigned longs, you are changing the types of the operands. And, now, you'll get...
    (ulong) = (uchar) + (uchar) * (ulong) + (uchar) * (ulong);
    
       /* Is reduced to */
    
    (ulong) = (uchar) + (ulong) + (ulong);
    
       /* Which is reduced to */
    
    (ulong) = (ulong) + (ulong);
    
       /* Which is further reduced to */
    
    (ulong) = (ulong);
    And, that's precisely what you want.

    Jon

Children
More questions in this forum