结构体类型重声明导致的bug一个

yutingliuyl yutingliuyl     2022-09-04     292

关键词:

bug前提条件

当模块比較多。头文件较多,某个结构体类型会在当前模块中又一次声明进而引用其成员,而不直接包括其它模块的头文件。

这种优点是不引入不须要的类型声明到此模块。头文件包括的交叉;坏处是,添加了bug的几率,耦合太大!比方以下一种情况发生而导致bug:

已知两个模块A和B。同一个结构类型struct node在两个模块中分别声明。当中B模块无意或者有意调整了结构类型中的某些域。那么这个时候。若B模块中引用A模块中此类型实例然后訪问成员变量,就会引发bug!

例如以下重现演示样例

bug重现演示样例代码

moduleA.c

#include <stdio.h>
struct node{
	char *name;
	void *data;
};

//定义測试变量
struct node new = {
	"TuoLuoFuSiJi",
	NULL
};

//測试输出
extern test_output(void);
void output(void)
{
	printf("%s
", new.name);	
}

int main(int argc, char *argv[])
{
	printf("call output:
");
	output();
	printf("call test_output:
");
	test_output();
	return 0;
}

moudleB.c

#include <stdio.h>
//这里又一次声明,调整域的顺序
struct node{
	void *data;
	char *name;
};

//引用moduleA中的new实例
extern struct node new;

void test_output(void)
{
	if(new.name)
		printf("%s
", new.name);	
	else
		printf("name is null
");
}
Makefile

run: moduleA.o moduleB.o
	cc -o run moduleA.o moduleB.o

运行结果:

技术分享


结果分析:

在模块B中,对name的訪问偏移量计算是根据本模块中的声明决定的。name的偏移量是4!

同理。在模块A中,name的偏移量是0.在模块B中訪问模块A中实例new时,

依照偏移量4计算。得到的确是data的值。显然为NULL。

解决的方法:

建议办法

1-往上提升;公共的类型声明。定义成一个全局性的头文件,多个模块共同使用。而不隶属与不论什么一方,避免交织

2-合作协商;两个模块的绝对一致。即一方改变(比方增删成员。或者改域名),必须通知还有一方

3-模块接口化。假设外面模块须要訪问本模块的实例。那么本模块应该提供接口。而不是让其它模块直接訪问自己模块的实例!这样是最理想的。

也符合高内聚,低耦合原则。

个人认为(3)是最理想的解决的方法。








c++结构体的输出

关于c++的结构,我才刚学,但是发现,原来我是不知道怎样输出结构体的内容啊.请各位大虾帮忙啊....就给我有关学生资料的结构体就行了可以通过下面的声明来建立如图的数据类型。复制纯文本新窗口structStudent//声明一个结构... 查看详情

[golang]语法基础之结构体(代码片段)

...最常用的方法是使用关键字struct,它可以让用户创建一个结构类型。而另外一种是之前说过的通过type自定义类型。通过结构体,可以创建带有成员的复合类型。使用结构体成员是由一系列的成员变量构成,这些成员变量也被称... 查看详情

结构体对齐

...以在一个存储区里记录多个相关数字这种存储区的类型叫结构体类型,这种类型需要首先创建出来然后才能使用2结构体类型存储区里包含多个子存储区,每个子存储区可以记录一个数字,结构体中不同子存储区的类型可以不同... 查看详情

结构体(struct)(代码片段)

结构体 结构体是将不同类型的数据安装一定的功能需求进行整体封装,封装的数据类型与大小均可以由用户指定。1结构体的声明、定义及初始化1.1声明结构体类型struct结构体名成员列表;;structSTUDENTcharname[20];//名字intage;//... 查看详情

c语言—自定义类型

目录​​一、结构体​​​​1、结构体的声明​​​​2、结构体的自引用​​​​3、结构体变量的定义和初始化​​​​4、结构体变量的访问​​​​5、结构体内存对齐​​​​6、结构体传参​​​​7、位段​​​​二、... 查看详情

c语言—自定义类型

目录​​一、结构体​​​​1、结构体的声明​​​​2、结构体的自引用​​​​3、结构体变量的定义和初始化​​​​4、结构体变量的访问​​​​5、结构体内存对齐​​​​6、结构体传参​​​​7、位段​​​​二、... 查看详情

头文件重复包含

设想一种情形:在c3.h中定义一个结构体类型,之前说过结构体类型、宏、类型重命名都是放到头文件里面的。当然放在源文件中也行,不过一般这些声明都是放在头文件中,这是一个规范!!因为它本身就是一个类型,可能在... 查看详情

浅谈结构体,结构体内存对齐(代码片段)

@TOC结构体及结构体的内存对齐结构体的定义结构体的基本知识结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。结构体的定义例如描述一个学生structStucharname[20];intage;charid[20];;在声明结... 查看详情

自定义类型:结构体

1.结构体的声明1.1结构的基础知识结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。数组则是一组相同类型元素的集合。1.2结构的声明生活中有很多很多的类型,像学生,老师,公务员,程序... 查看详情

c语言自定义数据类型之结构体

一、结构体1.1结构体的声明语法struct对象名成员列表;;1.2结构体声明的解释结构体其实与我们在数学中学过的集合本质相同比如,现在有一个描述房子的集合,集合里有许多元素,有的元素描述房子的大小,有的元素描述房子... 查看详情

c语言—自定义类型

一、结构体1、结构体的声明结构基础知识结构是一些值的集合,这些值被称为成员变量,结构的每个成员可以是不同类型的变量。​结构体的声明structtagmember-list;//成员列表variable-list;//变量列表实例:b1,b2,b3,b4,b5,b6,都是结构... 查看详情

c语言结构体(结构体类型定义|结构体类型别名|声明结构体变量的三种方法|栈内存中声明结构体变量|定义隐式结构体时声明变量|定义普通结构体时声明变量)(代码片段)

文章目录一、结构体类型定义二、结构体类型别名三、结构体类型变量声明1、使用结构体类型(别名)声明变量2、定义隐式结构体时声明变量3、定义普通结构体时声明变量二、完整代码示例一、结构体类型定义使用struct关键字,定... 查看详情

自定义类型详解(代码片段)

自定义类型种类:结构体枚举联合文章目录结构体结构体的定义结构体的声明结构体类型变量的定义1.先声明结构体类型,再定义该类型变量:**结构体变量初始化如图**2.在声明的同时定义变量:**结构体变量初始... 查看详情

自定义类型详解

一、结构体在C语言中有int,char,float等等类型,可以用来形容某些数据,但是有些数据仅靠一种类型无法描述出来,比如说一个人,我们不仅要描述他的名字,还要描述他的身高、体重、性别等特征。此时我们我发一种C语言自... 查看详情

20160221.ccpp体系详解(0031天)

程序片段(01):01.结构体静态数组.c+02.结构体动态数组.c内容概要:结构体数组///01.结构体静态数组.c#include<stdio.h>#include<stdlib.h>#include<string.h>//01.C语言的结构体特点://1.C语言要求结构体或者共用体至少得有一个成员//... 查看详情

c语言结构体定义

...dentintnum;structstudent*next;;这两种定义有什么区别?谢谢C语言结构体定义:struct为结构体关键字,tag为结构体的标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结构体声明的变量。结构体是C语言中聚合数... 查看详情

七c语言之结构体(代码片段)

目录1、结构体类型的声明 1.1结构体的基础知识1.2结构的声明1.3结构成员的类型2、结构体初始化2.1结构体变量的定义和初始化3、结构体成员访问1、结构体类型的声明 1.1结构体的基础知识结构是一些值的集合,这些值称为... 查看详情

复杂类型及编译相关

...    4)typedef能够定义复杂类型,宏定义则不行。2.结构体:将多种数据类型合并成为一种复合类型,以后用这种类型声明一个变量,那么这个变量就会拥有多个对应的数据类型数据。  1)格式:structstudent      int... 查看详情