Home > Blockchain >  aligned arrays of length zero in struct
aligned arrays of length zero in struct

Time:05-10

struct net_buf_simple {
    /** Pointer to the start of data in the buffer. */
    u8_t *data;
    /** Length of the data behind the data pointer. */
    u16_t len;
    /** Amount of data that this buffer can store. */
    u16_t size;
    u8_t __buf[0] __attribute__ ((aligned(4)));
    /** Start of the data storage. Not to be accessed directly
     *  (the data pointer should be used instead).
     */
};

int main()
{
    struct net_buf_simple buf_a;
    uint8_t array[4];
    buf_a.data = array;
    
    printf("buf_a:%p, data:%p, len:%p, size:%p, __buf:%p  sizeof(int):%d\n",  &buf_a, buf_a.data, &buf_a.len, &buf_a.size, buf_a.__buf, sizeof(int));

    return 0;
}

buf_a:0x7ffc7a0f7930, data:0x555cd091e740, len:0x7ffc7a0f7938, size:0x7ffc7a0f793a, __buf:0x7ffc7a0f793c  sizeof(int):4

I'm confused about the print address: there are 2 bytes before buf_a.len? The address buf_a.data is at the end of the struct? Shouldn't the __buf[0] point to the buf_a.data directly?

CodePudding user response:

There is no unaccounted for space at the front of the struct.

However, even if we remove the aligned on __buf, it still does alignment of the struct length.

Unless, we add __attribute__((packed)) to the struct definition.


Here is a modified version of your code to produce a test program:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

typedef unsigned char u8_t;
typedef unsigned short u16_t;

typedef struct net_buf_simple {
    /** Pointer to the start of data in the buffer. */
    u8_t *data;

    /** Length of the data behind the data pointer. */
    u16_t len;

    /** Amount of data that this buffer can store. */
    u16_t size;

#if NOALIGN
    u8_t __buf[0];
#else
    u8_t __buf[0] __attribute__ ((aligned(4)));
#endif
    /** Start of the data storage. Not to be accessed directly
     *  (the data pointer should be used instead).
     */
}
#if PACKED
__attribute__((packed))
#endif
bufsimp;

#define SHOWP(_sym) \
    printf("  " #_sym " ptr=%p off=%zu (offsetof %zu, width %zu)\n", \
        bufp->_sym,(char *) bufp->_sym - (char *) bufp, \
        offsetof(bufsimp,_sym),sizeof(bufp->_sym))

#define SHOWI(_sym) \
    printf("  " #_sym " val=%u (offsetof %zu, width %zu)\n", \
        bufp->_sym, \
        offsetof(bufsimp,_sym),sizeof(bufp->_sym))

bufsimp *
newbuf(int cap)
{

    bufsimp *bufp = malloc(sizeof(bufsimp)   cap);

    bufp->data = bufp->__buf;
    bufp->size = cap;
    bufp->len = 0;

    return bufp;
}

void
showbuf(bufsimp *bufp,const char *sym)
{
    printf("showbuf: %s\n",sym);
    printf("  bufp %p\n",bufp);
    SHOWP(data);
    SHOWI(len);
    SHOWI(size);
    SHOWP(__buf);
}

int
main(void)
{

    printf("sizeof=%zu\n",sizeof(bufsimp));

    bufsimp *buf_a = newbuf(4);
    showbuf(buf_a,"buf_a");

#if HAVEB
    bufsimp *buf_b = newbuf(16);
    showbuf(buf_b,"buf_b");
#endif

    return 0;
}

Here is the output of the program compiled normally:

sizeof=16
showbuf: buf_a
  bufp 0x21f4270
  data ptr=0x21f427c off=12 (offsetof 0, width 8)
  len val=0 (offsetof 8, width 2)
  size val=4 (offsetof 10, width 2)
  __buf ptr=0x21f427c off=12 (offsetof 12, width 0)

Here is the output with -DNOALIGN:

sizeof=16
showbuf: buf_a
  bufp 0x16e1270
  data ptr=0x16e127c off=12 (offsetof 0, width 8)
  len val=0 (offsetof 8, width 2)
  size val=4 (offsetof 10, width 2)
  __buf ptr=0x16e127c off=12 (offsetof 12, width 0)

Here is the output with: -DNOALIGN -DPACKED:

sizeof=12
showbuf: buf_a
  bufp 0xd09270
  data ptr=0xd0927c off=12 (offsetof 0, width 8)
  len val=0 (offsetof 8, width 2)
  size val=4 (offsetof 10, width 2)
  __buf ptr=0xd0927c off=12 (offsetof 12, width 0)
  • Related