This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

printing sizeof() values

I'm trying to print out sizeof() values for some of my structures. They are coming out incorrect. Here is a small table in which I've done this on different platforms:

Linux : sizeof(TChannel) = 1460
Windows: sizeof(TChannel) = 1460
8051 : sizeof(TChannel) = 1361

Are there byte-alignment issues perhaps? I have both Linux and Windows defaulting to a 1-byte boundary for byte alignment in structures. Does the 8051 default to something different?

Here's my code for the 8051:
Debugf( "sizeof(TChannel) = %u\r\n", sizeof( TChannel ) );

I've tried %u, %d, %lu, %bu, %X but can't get the right value. Here's my Debugf() function in case that might be messing things up:

void Debugf(BYTE* format, ...)
{
#ifdef DEBUG
xdata BYTE buf[64];
va_list arglist;
va_start (arglist,format);
vsprintf(buf,format,arglist);
va_end (arglist);
SendSerialData( buf, strlen( buf ) );
#endif
}

I don't think the problem is in my SendSerialData() function as that seems to work well.

Any ideas?

Parents
  • As you found, sizeof should be cast but do you not know that the compiler is free to insert pad bytes in structs *after* the first element for alignment purposes? On the 8051, aligment is to 1 byte thus all structs are "packed". On a 16-bit machine typically padded to 2 bytes, with a 32-bit machine padding to 4 usually.

Reply
  • As you found, sizeof should be cast but do you not know that the compiler is free to insert pad bytes in structs *after* the first element for alignment purposes? On the 8051, aligment is to 1 byte thus all structs are "packed". On a 16-bit machine typically padded to 2 bytes, with a 32-bit machine padding to 4 usually.

Children

  • ISO C99 has finally gotten around to supplying some standard types with specific sizes. <inttypes.h> will give you int8_t, uint8_t, and so on. It also provides some "half-open" types, so you can express the notion of "most convenient/fastest unsigned integer type as long as it's at least 16 bits wide" (uint_least16_t/uint_fast16_t), uintmax_t, intptr_t, conversion and limits macros galore, and so on.

    Not quite as terse as my favorites (U8, etc), and we're all already used to our home-grown solutions, but support should be available on multiple platforms without having to define them yourself.

    They also add a "bool" type, which of course introduces all sorts of interesting questions for every platform provider as to how it's implemented.

  • "On a 16-bit machine typically padded to 2 bytes, with a 32-bit machine padding to 4 usually."

    I'm sure Mark knows this already, but for the general reader:

    It can get even more complicated than that; eg, a 32-bit machine may be happy with unaligned 8-bit values, 16-bit values aligned on any even boundary, but 32-bit (or larger) values may need the 4-byte alignment.
    The compiler may allow you to override this and 'pack' your structures, but that may bring a serious performance hit!!

    As I keep saying, this is where it is essential that you fully read and understand the compiler Manual - particularly the section on internal data representation!