Thread: sizeof and Expression Evaluation

  1. #1
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005

    sizeof and Expression Evaluation

    I have some code similar to the following. I have highlighted the expression in question.
    Code:
    #include <stdio.h>
    
    #define ADDRESS 0x400
    
    struct sType1
    {
       unsigned char c;
       unsigned int  i;
    } Object1 = {5,0};
    
    struct sType2
    {
       unsigned char a;
       unsigned char b;
       unsigned char d[50];
       unsigned int  e;
    } Object2;
    
    int foo(void)
    {
       unsigned int addr1, addr2  = ADDRESS + (sizeof(Object2) * (Object1.c - 1));
       addr1  = Object1.c - 1; /* implicit cast of char */
       addr1 *= sizeof(Object2);
       addr1 += ADDRESS;
       return addr1 == addr2;
    }
    
    int main ( void )
    {
       printf("foo() = %d\n", foo());
       return 0;
    }
    The problem I have encountered is that the compiler generates code to do a csmul, which I take to mean a signed character multiply. In this example, it assigns addr2 with a value of 0x3D8. The correct value should be 0x4D8, and is correctly calculated (for the values of Object1.c that I've tested) when broken into smaller, simpler expressions.

    In stddef.h, size_t is typedefed as an unsigned int. And the platform has 8-bit bytes and 2-byte ints. The question I have is whether or not the compiler is incorrect here.
    Code:
    unsigned int addr2  = ADDRESS + (sizeof(Object2) * (Object1.c - 1));
    I would have expected that the result of the highlighted subexpression should have been an int. But even if the result were an unsigned char, this result multiplied by the size_t result should have been promoted to unsigned int(?). Or since the sizeof result was a constant in this expression, does the compiler have some leeway in this kind of expression?

    If the compiler is correct, I would welcome any explanation from those who understand the "usual arithmetic conversions" better than I can read from the standard.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    On the face of it, your compiler is broken.
    I compiled the code using gcc version 3.2 and got these results.

    addr1=4e0 addr2=4e0
    foo() = 1

    You could try
    addr2 = ADDRESS + (sizeof(Object2) * ((unsigned int)Object1.c - 1));
    to see if the compiler gets the message.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Originally posted by Salem
    You could try
    addr2 = ADDRESS + (sizeof(Object2) * ((unsigned int)Object1.c - 1));
    to see if the compiler gets the message.
    Yeah, that does jerk it into cooperation. I had tried that too before going with the (in my opinion) 'less cluttered' version. But after you posted, I double-checked and found that it generated slightly less assembly (likely because it did not need the intermediate stores).

    I've also been trying to wander through the documentation to see whether there is some option that may be disabling the integer promotions. (I know that it uses a single byte for a variable of enum type with small values.) And I also discovered that the 'signed multiply', both char and int, appear to be the same as the 'unsigned multiply' -- the emulator reports one thing, but the assembly listing says another.

    Thank you for the reply.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Little Array Difficulty
    By G4B3 in forum C Programming
    Replies: 16
    Last Post: 03-19-2008, 12:59 AM
  2. Converting to expression to string of array elements
    By Sailors in forum C Programming
    Replies: 12
    Last Post: 07-26-2007, 03:01 PM
  3. sizeof pointer-to-array -- &array
    By josemariasola in forum C Programming
    Replies: 19
    Last Post: 07-15-2006, 06:39 PM
  4. Question on l-values.
    By Hulag in forum C++ Programming
    Replies: 6
    Last Post: 10-13-2005, 04:33 PM
  5. sizeof question
    By CrackerJack in forum C Programming
    Replies: 1
    Last Post: 11-09-2003, 03:09 AM