C成员的结构顺序
我正在接管一段代码..linux中的c编程。我对结构做了一个小改动C成员的结构顺序,c,struct,C,Struct,我正在接管一段代码..linux中的c编程。我对结构做了一个小改动 typedef struct { unsigned int a1; .. .. .. float f1; unsigned int a2; unsigned int a3; unsigned int offending; // shifted this } test; 我将unsigned int offline移到float f1之前,如下所示: typedef struct { uns
typedef struct {
unsigned int a1;
..
..
..
float f1;
unsigned int a2;
unsigned int a3;
unsigned int offending; // shifted this
} test;
我将unsigned int offline移到float f1之前,如下所示:
typedef struct {
unsigned int a1;
..
..
..
unsigned int offending;
float f1;
unsigned int a2;
unsigned int a3;
} test;
代码崩溃了。。。有什么问题吗
c结构的成员顺序重要吗 有什么问题吗?取决于代码的其余部分,以及您还做了什么 不,结构成员的顺序本质上并不重要。当其他代码依赖它时,它就是这样做的 可能的原因(并非详尽无遗):
- 您没有重新编译所有内容,并且此结构或其某些方面存在外部链接
- 通过移动成员,您更改了其他成员的对齐方式和/或结构的sizeof(),并且没有对此进行补偿
- 某个地方有一个文字常量或宏,其大小或偏移量取决于此结构
- 有一些错误代码以前从未失败过,但现在由于内存布局的改变而失败了
- 该结构被用作另一个结构或联合的一部分,问题与此相关
- 有一个使用{}的列表初始化,它不再匹配成员顺序
编辑:ht@Jens.可能是什么问题?取决于代码的其余部分,以及您还做了什么 不,结构成员的顺序本质上并不重要。当其他代码依赖它时,它就是这样做的 可能的原因(并非详尽无遗):
- 您没有重新编译所有内容,并且此结构或其某些方面存在外部链接
- 通过移动成员,您更改了其他成员的对齐方式和/或结构的sizeof(),并且没有对此进行补偿
- 某个地方有一个文字常量或宏,其大小或偏移量取决于此结构
- 有一些错误代码以前从未失败过,但现在由于内存布局的改变而失败了
- 该结构被用作另一个结构或联合的一部分,问题与此相关
- 有一个使用{}的列表初始化,它不再匹配成员顺序
编辑:ht@Jens.如果更改数据布局,最可能导致崩溃的原因是初始化。如果代码中有使用声明顺序的旧初始值设定项,那么字段会突然收到与以前不同的值。因此,自C99以来的现代C已指定了可避免该问题的初始值设定项:
test toto = { 32, ... , 42, }; // sensible to reordering
test tata = { .a1 = 32, ... , .offending = 42, }; // still the same
如果更改数据布局,最可能导致崩溃的原因是初始化。如果代码中有使用声明顺序的旧初始值设定项,那么字段会突然收到与以前不同的值。因此,自C99以来的现代C已指定了可避免该问题的初始值设定项:
test toto = { 32, ... , 42, }; // sensible to reordering
test tata = { .a1 = 32, ... , .offending = 42, }; // still the same
这是否会改变结构的内存布局取决于实现。如果您有另一段代码,比如说,在结构中查找64位的内容,那么它现在得到的是它不期望的数据。这是否与另一个未重新编译的软件相关?或者这是独立的。此外,根据实现的不同,如果它破坏了编译器使用的对齐方式,那么最终可能会更改类型的总大小。“可能是什么问题?”—代码的问题还是您遇到的问题?对于前者,我们无法回答,因为除了结构typedef之外,我们什么也看不到。后者可能是因为您在不了解布局在代码中的使用方式的情况下更改了布局,并且未能解释某些内容(例如:使用旧布局从磁盘读取以前保存的数据的二进制结构,使用旧版本编译的客户机/服务器的套接字不知道新版本,等等).同意上述意见。如果make文件没有正确的依赖项,它可能无法重新编译依赖于此结构的文件。整个崩溃代码都应该包含在问题中,否则我们不知道是什么导致了问题。重要的是要了解,虽然您通常不使用
struct+offset
访问结构的成员,有很多数据结构可以做到这一点。尤其是在诸如链表这样的结构中,对于泛型实现采用void类型。在这里,结构中成员的顺序是至关重要的。在这种情况下,改变顺序很容易看出它是如何导致崩溃的。这是否会改变结构的内存布局取决于实现。如果您有另一段代码,比如说,在结构中查找64位的内容,那么它现在得到的是它不期望的数据。这是否与另一个未重新编译的软件相关?或者这是独立的。此外,根据实现的不同,如果它破坏了编译器使用的对齐方式,那么最终可能会更改类型的总大小。“可能是什么问题?”—代码的问题还是您遇到的问题?对于前者,我们无法回答,因为除了结构typedef之外,我们什么也看不到。后者可能是因为您在不了解布局在代码中的使用方式的情况下更改了布局,并且未能解释某些内容(例如:使用旧布局从磁盘读取以前保存的数据的二进制结构,使用旧版本编译的客户机/服务器的套接字不知道新版本,等等).同意上述意见。如果make文件没有正确的依赖项,它可能无法重新编译依赖于此结构的文件。整个崩溃代码应该包含在问题中,否则我们不知道是什么导致了问题。重要的是要理解,虽然您通常不使用struct+offset
访问