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

Confused by keil mdk struct alignment

typedef uint8_t BDADDR_t[6];
typedef struct
{
        uint8_t  State;
        BDADDR_t RemoteBDADDR;
        uint16_t DataPacketsQueued;
        uint16_t Handle;
        uint8_t  LinkType;
        uint8_t  CurrentIdentifier;
        bool     LocallyInitiated;
}ATTR_PACKED BT_HCI_Connection_t;
BT_HCI_Connection_t HCIConnection;

The address of HCIConnection is:0x1000004E and the memory data start from 0x1000004E is as following:
03 10 a3 15 83 15 00 00.
So I think the State = 03; the BDADDR is 00 15 83 15 a3 10, but the watch window show that the BDADDR is 00 00 15 83 15 a3.
So what should I do to get the correct value of a mix typed struct?

Another question:
Does the effect of #pragma pack(1) is the same as __packed ?
Thanks!

chris

  • What you have learned is the important lesson that you should never make assumptions about where a compiler inserts padding in structs - so don't write code that requires such assumptions.

    The compiler may decide that the array is of byte type and can be placed at an odd address. And the compiler can decide that having a pad before the array or after the array makes a difference in number of memory accesses needed to access the full size of the array - after all, a non-packed struct requires the following 16-bit member to be aligned.

    Remember also that copying of raw data that is sent over a wire or picked up from memory card etc doesn't take into account the byte order for the sender and receiver. And using pragma or other meta-attributes to pack a struct will not take care of incorrect byte order. It is normally best to explicitly pack/unpack data when sharing data over a communication link.

  • you should never make assumptions about where a compiler inserts padding in structs

    Never say never.
    Here is a structure from uIP:

    struct arp_hdr {
      struct uip_eth_hdr ethhdr;
      u16_t hwtype;
      u16_t protocol;
      u8_t hwlen;
      u8_t protolen;
      u16_t opcode;
      struct uip_eth_addr shwaddr;
      uip_ipaddr_t sipaddr;
      struct uip_eth_addr dhwaddr;
      uip_ipaddr_t dipaddr;
    };
    


    This structure is used to access the actual ARP header inside a packet buffer. As you can see, it does assume that the compiler will not insert any padding. You'll be surprised to know how well this works on a wide variety of platforms.
    But I agree, this should probably be considered a hack.

  • http://www.keil.com/forum/21537/

    somesay no never some say yes. how can we know what is right?

  • Easy. When you see the word 'never,' replace it with 'this doesn't sound like a good idea, make sure you know what you are doing.'

  • Exactly - in this case the struct have the size and location of all fields carefully selected and ordered to maximize the probability of compilers placing them similarly. Two byte variables can be stored before or after a 16-bit variable and two 16-bit variables can be stored before/after a 32-bit variable while maintaining 16-bit or 32-bit align without need for any pad.

    It is always possible to place struct fields in ways that gives better/worse probability. Then the developer have to decide the value of _assuming_ that no extra padding have been added contra the oops if the assumption was wrong.

    Next thing is that networking code contains macros or functions for converting fields between network and host byte order.

  • Does the effect of #pragma pack(1) is the same as __packed ?

    No, there are differences. But the effect that you likely care about is the same. You should read the manual for details.

    www.keil.com/.../armccref_CJAFEEDG.htm

    www.keil.com/.../armccref_CJAFJHJD.htm

  • Note that I didn't write just "never". I did write "never make assumptions". If you can prove your assumption always true then you are home free.

    But the majority of assumptions doesn't even make it as far as a comment in the source code "This code assumes that the compiler ..." and it is even less common that there are some form of test bench or assert solution to validate the functionality.

    So applications tends to be released because they "seem to work", based on testing by a tester who don't even know that the product is a house of cards built based on undocumented assumptions.

  • So here I need to place linkType behind the State member? Thanks!

    Chris