Struct w/ bit field: CPython and C padding differs

Viewed 1609

Consider the following program:

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

typedef struct
{
    unsigned        bit:1;
    unsigned char   str[8];
} test;

#pragma pack(1)
typedef struct
{
    unsigned        bit:1;
    unsigned char   str[8];
} test_pack;

int main(int argc, char **argv) {

    printf("%3lu str offset\n", offsetof(test, str));
    printf("%3lu total\n", sizeof(test));

    printf("%3lu str_pack offset\n", offsetof(test_pack, str));
    printf("%3lu total\n", sizeof(test_pack));

    return 0;
}

which outputs

  1 str offset
 12 total
  1 str_pack offset
  9 total

on my Ubuntu 14.04.3 system with GCC 4.8.4.

The (I think) equivalent Python program,

#!/usr/bin/python3

from ctypes import *

class Test(Structure):
    _fields_ = [
        ('bit', c_uint, 1),
        ('str', c_ubyte * 8),
    ]

class TestPacked(Structure): 
    _pack_ = 1
    _fields_ = [
        ('bit_p', c_uint, 1),
        ('str_p', c_ubyte * 8),
    ]

if __name__ == "__main__":
    print("%3lu str offset" % Test.str.offset)
    print("%3lu total" % sizeof(Test))

    print("%3lu str_p offset" % TestPacked.str_p.offset)
    print("%3lu total_p" % sizeof(TestPacked))

outputs

  4 str offset
 12 total
  4 str_p offset
 12 total_p

On the same system, running Python 3.4.0.

From what I can tell, the bit field should take up 1 bit. C and Python both pad that to 32 bits, adding 3 bytes of empty space to the struct so it aligns better.

However, Python puts the padding before the string and C puts it after.

Also, with #pragma pack(1), C removes the padding but Python doesn't.

  • Can I get python to add the 3 bytes of padding after the string instead of before?
  • Failing that, could python pack the struct properly so that they line up?

Doesn't need to work across different systems over a network protocol or anything... Just trying to get the bits to line up on one system, even if I have to reconfigure it somehow. Thanks!

3 Answers

It is probably a duplicate of this well known problem : https://bugs.python.org/issue29753 A patch has been validated few month ago but is not yet merged in the official sources.

Related