2017-03-01 55 views
0

我真的很感激,如果任何解释可以给出下面的一段代码的输出。我不明白为什么sizeof(struct_2)sizeof(my_struct_2)是不同的,提供sizeof(struct_1)sizeof(c_int)相同为什么sizeof在ctypes struct packing的给定示例中有所不同?

看来​​包装structstruct以不同的方式吗?

from ctypes import * 

class struct_1(Structure): 
    pass 
int8_t = c_int8 
int16_t = c_int16 
uint8_t = c_uint8 
struct_1._fields_ = [ 
    ('tt1', int16_t), 
    ('tt2', uint8_t), 
    ('tt3', uint8_t), 
] 

class struct_2(Structure): 
    pass 
int8_t = c_int8 
int16_t = c_int16 
uint8_t = c_uint8 
struct_2._fields_ = [ 
    ('t1', int8_t), 
    ('t2', uint8_t), 
    ('t3', uint8_t), 
    ('t4', uint8_t), 
    ('t5', int16_t), 
    ('t6', struct_1), 
    ('t7', struct_1 * 6), 
] 

class my_struct_2(Structure): 
    #_pack_ = 1 # This will give answer as 34 
    #_pack_ = 4 #36 
    _fields_ = [ 
    ('t1', c_int8), 
    ('t2', c_uint8), 
    ('t3', c_uint8), 
    ('t4', c_uint8), 
    ('t5', c_int16), 
    ('t6', c_int), 
    ('t7', c_int * 6), 
] 

print "size of c_int   : ", sizeof(c_int) 
print "size of struct_1   : ", sizeof(struct_1) 
print "size of my struct_2  : ", sizeof(my_struct_2) 
print "siz of origional struct_2: ", sizeof(struct_2) 

OUTPUT:

size of c_int   : 4 
size of struct_1   : 4 
size of my struct_2  : 36 
siz of origional struct_2: 34 ==> why not 36 ?? 

编辑: 重命名t6-> T7(struct_1的阵列)和从struct_2除去 = 2。但我仍然看到不同大小struct_2my_struct_2

+0

这是什么语言?如果“C”使用了我不熟悉的扩展名。 –

+0

对我来说看起来像Python,而不是C. – Barmar

+0

我认为这是因为'struct_2'是打包的,所以't5'后面没有填充。但'my_struct_2'没有打包,所以't5'和't6'之间有2个字节的填充字符以使它字对齐。 – Barmar

回答

0

的差异起因于存在或不存在之间或在结构布局元素后的填充物,因为当尺寸不同时,较大的一个占比所需的更多的字节所有的个人结构成员。单独的成员t5t6就足以证明不同之处,并且如果省略t5(仅),则不存在差异。

一个小的实验表明,在默认情况下(当没有指定即_pack_构件),ctypes的提供了用于结构类型struct_1,但4字节对齐为c_int类型2字节对齐。无论如何,它在我的系统上都有。 ctypes文档声称,默认情况下,它按照系统的C编译器(默认情况下)的方式来布局结构,并且确实如此。考虑这个C程序:

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

int main() { 
    struct s { 
     int16_t x; 
     int8_t y; 
     uint8_t z; 
    }; 
    struct t1 { 
     int16_t x; 
     struct s y; 
    }; 
    struct t2 { 
     int16_t x; 
     int  y; 
    }; 

    printf("The size of int is  %zu\n", sizeof(int)); 
    printf("The size of struct s is %zu\n", sizeof(struct s)); 
    printf("The size of struct t1 is %zu\n", sizeof(struct t1)); 
    printf("The size of struct t2 is %zu\n", sizeof(struct t2)); 
    printf("\nThe offset of t1.y is %zu\n", offsetof(struct t1, y)); 
    printf("The offset of t2.y is %zu\n", offsetof(struct t2, y)); 
} 

及其对我输出(在CentOS7瓦特/在x86_64 GCC 4.8)是:

The size of int is  4 
The size of struct s is 4 
The size of struct t1 is 6 
The size of struct t2 is 8 

The offset of t1.y is 2 
The offset of t2.y is 4

观察到的intstruct s尺寸是相同的(4个字节),但编译器在struct t1内对齐struct s的2字节边界,而它在struct t2内的4字节边界上对齐int。这与ctypes在同一系统上的行为完美匹配。

至于为什么 GCC选择它的取向,我观察到如果我到struct s然后GCC开关int类型的成员添加到使用4字节对齐的结构,以及排列(默认)该结构内的int的偏移量为4个字节的倍数。有理由得出结论:GCC在结构中布局成员并选择结构的整体对齐,以便每个对齐的结构实例的所有成员本身自然对齐。但请注意,这只是一个例子。 C的实现在很大程度上取决于他们自己决定选择结构布局和对齐要求。

+0

ctypes为结构类型提供2字节对齐方式struct_1 >>如果我明确使用__pack_ = 4,那么我会看到不同的大小。 –

+0

如果我们使用C代码中的对齐和打包,那么它给出了预期的大小 struct t1 {intl_t x; struct s y; } __attribute__((packed,aligned(4))); INT的大小是4 结构S的大小为4 结构T1的大小是8 结构T2的大小是8 的t1.y的偏移量为2 t2.y的偏移是4 我们如何在python中获得与ctypes相同的行为? _pack_ = 4不起作用。 –

+0

@AmitSharma,你误解了'_pack_'的含义。它设置*最大*对齐。通过将其设置为较小的数字,您可以获得更少的填充或甚至没有填充,但通过将其设置为更大的数字不能强制填充更多。但是,您可以通过添加一个您自己忽略的成员手动*填充结构。 –

相关问题