Packed Structures in C++ Tools

One of the Newton 2.x OS Q&As
Copyright © 1997 Newton, Inc. All Rights Reserved. Newton, Newton Technology, Newton Works, the Newton, Inc. logo, the Newton Technology logo, the Light Bulb logo and MessagePad are trademarks of Newton, Inc. and may be registered in the U.S.A. and other countries. Windows is a registered trademark of Microsoft Corp. All other trademarks and company names are the intellectual property of their respective owners.


For the most recent version of the Q&As on the World Wide Web, check the URL: http://www.newton-inc.com/dev/techinfo/qa/qa.htm
If you've copied this file locally, click here to go to the main Newton Q&A page.
This document was exported on 7/23/97.


Packed Structures in C++ Tools (2/28/97)

Q: Do the Newton C++ Tools support a concept of packed structures? Some compilers provide a keyword (packed) to prevent aligning of the fields by the compiler. I tried to use the keyword and got an error. How can I ensure that a structure is packed?

A: While there is no supported way to do this in the current tools, the ARM compiler does have an experimental directive, __packed, which is probably worth a try. Using this directive may cause the compiler to stop with an internal error in some circumstances, so be prepared. You should ensure that the structure produced has the correct alignment by using the C sizeof and offsetof functions, since this directive does introduce a compiler dependency. Accessing elements in __packed structures can be considerably less efficient than using non-packed structures: use them only when necessary. For example:
    __packed struct T { char c; int i; };

produces a structure that is 5 bytes wide. Without the __packed directive, it would be 8 bytes wide and the integer field would begin 4 bytes from the structure start, so that it was word aligned.

We believe the internal error in the compiler can be avoided by taking the sizeof the structure before using it. An easy way to do this is to add a dummy function right after the structure is declared. For example:
inline void dummyT() { (void)sizeof(T); }

Primitive types can also be declared __packed, which means that the compiler will not make assumptions about the alignment of pointers to them. That is, if you know an int starts two bytes into a word-aligned data structure, the wrong thing will happen if you simply cast the pointer to int. Instead, you can used an unaligned int type. This generates considerably less efficient code than is needed for working with aligned values, but it's still more efficient that trying to extract the proper bytes and shift/add them into an integer youself. For example:
    typedef __packed int UNALIGNED_INT;
    int IntAt(UNALIGNED_INT* p) { return *p; }


This directive does not work properly with bitfield specifiers. For example:
        __packed struct Foo {
        unsigned flag1 : 1;
        unsigned flag2 : 1;
        unsigned data1 : 6;
        unsigned short data2;

}

will not produce what you expect. Instead, avoid the bitfield specifiers and take advantage of C++ inline functions to access the partial bytes:
        __packed struct Foo {
        char stuff;
        unsigned short data2;

        int Flag1() { return (stuff & 0x80) != 0; }
        int Flag2() { return (stuff & 0x40) != 0; }
        int Data1() { return stuff & 0x3F; }
        int Data2() { return data2; }
    };
    inline void dummyFoo() { (void)sizeof(Foo); }


The result is a 3-byte wide data structure with the bitfields easily accessible.

Note that the ProtocolGen tool (part of the DDKs) does not understand the __packed directive. ProtocolGen does not make use of structure sizes, so it's OK to NOP out the __packed keyword for that tool. Here's an easy way to do that:
    #ifdef PROTOCOLGEN
    #define __packed

#endif