2017-10-14 55 views
2

我知道在C语言中,struct成员的顺序是它们声明的顺序加上(通常除非另有说明)否则可能发生填充,导致我创建的两个第一个结构体他们各自的大小:在C语言中订购优势的结构成员

struct MyStructV1 
{ 
    int a; 
    char c; 
    int b; 
}; 

printf("size of MyStructV1 is:%lu \n",sizeof(struct MyStructV1)); // prints 12 

struct MyStructV1Packed 
{ 
    int a; 
    char c; 
    int b; 
}__attribute__((__packed__));; 

printf("size of MyStructV1Packed is:%lu \n",sizeof(struct MyStructV1Packed)); // prints 9 

到目前为止好。

那么,我的问题是,下面的MyStructV2的“解压缩”版本声明与第一版​​MyStructV1相比有什么优点/好处吗?

struct MyStructV2 
{ 
    int a; 
    int b; 
    char c; 
}; 

printf("size of MyStructV2 is:%lu \n",sizeof(struct MyStructV2)); // prints 12 as well 

请注意,现在成员的顺序有变化(b在c之前声明)。

我指的是内存访问“成本”或周期需要完成,以读/写结构成员和/或任何其他相关的考虑因素?

它是依赖于编译器/架构(如果有的话)?

干杯,

盖伊。

+2

大多数并不重要,在所有的时间。您可能希望在较短的区域之前放置更广泛的区域。当然这取决于体系结构和ABI –

+1

它依赖于编译器。除此之外,一个非常好的经验法则是不要担心打包结构,除非你有一些体系结构和编译器特定的理由来这样做,并确切知道它是什么。否则,让编译器处理它并在它认为合适的地方插入一个或两个填充符会更好。 –

回答

4

第一个和最后一个版本之间应该没有什么区别。在这两个结构中,int成员都按字边界对齐,因此可以高效地从内存中读取它们。它们之间的唯一区别是填充范围在cb之间,在MyStructV1之间,结尾在MyStructV2之间。但是由于填充没有执行开销;访问结构成员只需通过向结构开头的地址添加一个已知的偏移量即可完成。在MyStructV1中,b的偏移量是8MyStructV24

+3

这不是100%的事实。特别是如果我们考虑结构包装。在许多平台上进行打包涉及字节访问,甚至可以阻止程序正常工作。例如:外设需要字或半字访问,但结构已打包并且是字节访问。包装被初学者过度使用,应小心使用 –

+0

@ PeterJ_01问题在于比较*不使用包装的两种结构。包装可以产生性能点击是正确的。 – Barmar

1

如果char小于int然后int(通常是这样),则结构MyStructV1可以小于MyStructV2。

根据环境(体系结构和编译器选项),struct MyStructV1可以封装一个pad或可以不对齐b。 根据体系结构的不同,如果b未加载,它可能需要更多的cpu时钟。

此外,根据架构的不同,读取a可以加载更多的内容以立即可用,如果存在填充项,则此优点将减少或丢失。

+0

非常非常差和不准确的答案。国际海事组织,你应该删除它 –

+0

恕我直言,这是一个简短的正确答案,我希望它是有用的人。 无论如何,如果你有不同的意见请详细说明。 –

0

这更有趣,当然还有订购事宜。

struct aaa1{ 
    char a; 
    char a1; 
    int b; 
}; 

struct aaa2{ 
    char a; 
    char a1; 
    char a2; 
    int b; 
}; 

struct aaa3{ 
    char a; 
    char a1; 
    char a2; 
    char a3; 
    int b; 
}; 

struct aaa4{ 
    char a1; 
    char a2; 
    char a3; 
    int b; 
    char a; 
}; 

int main(void) { 

struct aaa5{ 
    char a; 
    int b; 
    char a1; 
}; 


    printf("%zu %zu %zu %zu %zu %zu\n", sizeof(struct aaa), sizeof(struct aaa1), sizeof(struct aaa2), sizeof(struct aaa3), sizeof(struct aaa4), sizeof(struct aaa5)); 

输出:8 8 8 8 12 12