如果能够对下面一段代码的输出进行任何解释,我将非常感激。我不明白为什么sizeof(struct_2)
和sizeof(my_struct_2)
不同,提供 sizeof(struct_1)
而sizeof(c_int)
相同。
似乎ctypes
在struct
内以某种不同的方式打包struct
?
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)
输出:
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中删除 pack = 2。但我仍然看到struct_2
和my_struct_2
答案 0 :(得分:0)
差异源于结构布局中元素之间或之后是否存在填充,因为当大小不同时,较大的元素占所有单个结构成员所需的字节数。只有成员t5
和t6
足以证明其差异,如果省略t5
(仅限),则没有区别。
一些实验表明,默认情况下(即未指定_pack_
成员时),ctypes为结构类型struct_1
提供2字节对齐,但为类型{{1提供4字节对齐}}。或者它在我的系统上,无论如何。 ctypes文档声称默认情况下它以与系统的C编译器(默认情况下)相同的方式布局结构,而事实上似乎就是这种情况。考虑一下这个C程序:
c_int
我的输出(在x86_64上的CentOS 7 w / 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
注意#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));
}
和int
的大小相同(4个字节),但编译器在struct s
内的2字节边界上对齐struct s
,它将struct t1
与int
内的4字节边界对齐。这与同一系统上的ctypes行为完全匹配。
至于为什么 GCC选择它做的对齐,我观察到如果我将struct t2
类型的成员添加到int
,那么GCC会切换到使用4字节对齐对于结构,以及安排(默认情况下)结构中struct s
的偏移量为4个字节的倍数。可以合理地得出结论,GCC在结构中布置成员并选择整体结构的对齐,以便每个对齐的结构实例的所有成员本身自然对齐。但请注意,这只是一个例子。在选择结构布局和对齐要求方面,C实现主要由他们自行决定。