📜  C |结构与联合|问题10(1)

📅  最后修改于: 2023-12-03 15:13:47.384000             🧑  作者: Mango

C | 结构与联合 | 问题10

介绍

C语言中,结构和联合是最常用的两种构造体类型。它们都用来组织和管理复杂的数据,使得程序员可以更方便地处理大型数据结构。

结构和联合的使用方法较为类似,但是它们有着不同的特点和作用。本文将重点介绍结构和联合的定义和使用方法,并对它们常见的问题进行说明。

结构体

结构体是将多个数据类型的变量组合在一起的数据类型。它允许用户自定义一种数据类型,将不同的变量组合在一起形成一个大的数据类型,以方便程序员对数据进行封装、管理和使用。

结构体的基本语法如下:

struct struct_name {  

   member_type1 member_name1;  
   member_type2 member_name2;  
   //...  
   member_typeN member_nameN;  

};

其中,struct_name为定义的结构体名称,member_type则是变量的数据类型,member_name为变量的名称。

结构体的定义

下面是一个简单的结构体定义示例:

#include <stdio.h>
 
struct student {
   char name[50];
   int age;
   float gpa;
};
 
int main() {
   printf("%d", sizeof(struct student));
   return 0;
}

在上面的例子中,我们定义了一个student结构体,其包含了一个学生的姓名、年龄和GPA。由于每个成员类型的长度不同,因此我们可以使用sizeof函数来获取student结构体的大小。结果为:sizeof(struct student) = 56字节。

结构体的访问和操作

使用.操作符可以访问结构体中的成员变量。例如,要访问上面定义的student结构体中的成员变量,可以使用以下语法:

#include <stdio.h>
#include <string.h>
 
struct student {
   char name[50];
   int age;
   float gpa;
};
 
int main() {
   struct student s1;
   strcpy(s1.name, "张三");
   s1.age = 18;
   s1.gpa = 3.5;
 
   printf("姓名:%s,年龄:%d,GPA:%f\n", s1.name, s1.age, s1.gpa);
 
   return 0;
}

输出结果为:姓名:张三,年龄:18,GPA:3.5

我们还可以使用指向结构体的指针来访问和操作结构体变量。例如:

#include <stdio.h>
#include <string.h>
 
struct student {
   char name[50];
   int age;
   float gpa;
};
 
int main() {
   struct student s1 = {"李四", 19, 4.0};
   struct student *ptr = &s1;
 
   printf("姓名:%s,年龄:%d,GPA:%f\n", ptr->name, ptr->age, ptr->gpa);
 
   return 0;
}

输出结果为:姓名:李四,年龄:19,GPA:4.000000

结构体的嵌套

我们可以在结构体中嵌套其他的结构体,以便更好地处理复杂的数据结构。例如:

#include <stdio.h>
#include <string.h>
 
struct address {
   char street[50];
   char city[50];
   char state[50];
   int zip;
};
 
struct student {
   char name[50];
   int age;
   float gpa;
   struct address addr;
};
 
int main() {
   struct student s1 = {"王五", 20, 3.5, {"学院路", "上海", "上海市", 200000}};
 
   printf("姓名:%s,年龄:%d,GPA:%f\n", s1.name, s1.age, s1.gpa);
   printf("地址:%s,%s,%s,%d\n", s1.addr.street, s1.addr.city, s1.addr.state, s1.addr.zip);
 
   return 0;
}

输出结果为:

姓名:王五,年龄:20,GPA:3.500000
地址:学院路,上海,上海市,200000
联合体

联合体是一种特殊的结构体,它的所有成员都共享同一段内存空间。联合体中最大的一个成员就可以使用整个联合体的内存空间。使用联合体的好处是节省内存空间,但是也带来了一些特殊的问题。

联合体的基本语法如下:

union union_name {  
  
   member_type1 member_name1;  
   member_type2 member_name2;  
   //...  
   member_typeN member_nameN;  

};

其中,union_name为定义的联合体名称,member_type为变量的数据类型,member_name为变量的名称。

联合体的定义

下面是一个简单的联合体定义示例:

#include <stdio.h>
 
union value {
   int ival;
   float fval;
   char sval[20];
};
 
int main() {
   union value v1;
 
   v1.ival = 100;
   printf("int ival: %d\n", v1.ival);
   v1.fval = 123.45;
   printf("float fval: %f\n", v1.fval);
   strcpy(v1.sval, "hello");
   printf("char sval: %s\n", v1.sval);
 
   return 0;
}

在上面的例子中,我们定义了一个value联合体,其包含了一个整数、一个浮点数和一个字符串。我们使用不同类型的变量对联合体进行初始化,并使用.ival.fval.sval来引用这些变量。

联合体的访问和操作

使用.操作符可以访问联合体中的成员变量。例如,要访问上面定义的value联合体中的成员变量,可以使用以下语法:

#include <stdio.h>
 
union value {
   int ival;
   float fval;
   char sval[20];
};
 
int main() {
   union value v1;
   v1.ival = 100;
   printf("int ival: %d\n", v1.ival);
   v1.fval = 123.45;
   printf("float fval: %f\n", v1.fval);
   strcpy(v1.sval, "hello");
   printf("char sval: %s\n", v1.sval);
   printf("int ival: %d\n", v1.ival); // 注意:这里输出的结果不一定是100
   return 0;
}

输出结果为:

int ival: 100
float fval: 123.450005
char  sval: hello
int ival: 1112372111

由于联合体中的所有成员都共享同一段内存空间,因此对某个成员的修改可能会影响到其他成员的值。在上面的例子中,我们先将v1.ival的值设置为100,然后将v1.fval设置为123.45,这时候v1.ival的值就变成了1112372111,这并不是我们所预期的结果。因此,在使用联合体时,我们需要特别小心,避免出现不可预知的结果。

联合体的嵌套

我们也可以在联合体中嵌套其他的联合体或结构体,以便更好地处理复杂的数据结构。例如:

#include <stdio.h>
 
struct student {
   char name[20];
   union {
      int age;
      float gpa;
   } info;
};
 
int main() {
   struct student s1 = {"张三", {19}};
   struct student s2 = {"李四", {3.5}};
 
   printf("姓名:%s,年龄:%d\n", s1.name, s1.info.age);
   printf("姓名:%s,GPA:%f\n", s2.name, s2.info.gpa);
 
   return 0;
}

在上面的例子中,我们定义了一个student结构体,其包含了一个学生的姓名和信息。在信息中,我们使用了一个联合体,可以存储学生的年龄或GPA。因为联合体中所有成员共享同一段内存空间,所以我们将年龄和GPA存储在同一个联合体中,便于读取和使用。

结构体和联合体的区别

结构体和联合体在某些方面是相似的,但是它们也具有一些根本性的不同。下面是结构体和联合体的区别:

  • 结构体中的各个成员在内存中是按照次序一个接一个存放,它们都有自己的内存地址,因此可以同时访问结构体中的多个成员。联合体中所有成员共享同一个内存地址,每次只能访问其中的一个成员,修改一个成员可能会影响到其他成员。

  • 结构体的大小等于所有成员大小之和,不同的编译器对齐方式可能不同。联合体的大小等于最大成员的大小。

  • 结构体对于成员变量的命名没有限制,成员变量名可以相同;联合体对成员变量名有限制,所有成员变量名称需要一致。

  • 结构体适合处理多个不同的信息,而联合体适合处理同一段内存上的不同表示方式。

常见问题
结构体和联合体的定义区别

结构体和联合体的定义语法比较类似,都使用了大括号包含成员变量,但它们的功能和使用方式有很大区别。

结构体用于将多个变量结合在一起,形成一个新的复合数据类型,每个成员变量独立存储。结构体的大小等于所有成员大小之和。

联合体用于将同一段内存空间分配给不同的变量,共享内存空间,每次只能访问其中的一个成员。联合体的大小等于最大成员的大小。

结构体和联合体的区别是什么?

结构体和联合体的区别主要在于以下几点:

  • 结构体在内存中按照次序一个接一个存放,而联合体中所有成员共享同一个内存空间;

  • 结构体的大小等于所有成员大小之和,而联合体的大小等于最大成员的大小;

  • 结构体适合处理多个不同的信息,而联合体适合处理同一段内存上的不同表示方式。

什么时候使用结构体和联合体?

结构体和联合体适合处理不同类型的数据,它们可以将多个变量组合在一起,形成一个新的数据类型。结构体适合处理多个不同的信息,而联合体适合处理同一段内存上的不同表示方式。

当我们需要定义一种新的数据类型,或者需要处理复杂的数据结构时,可以使用结构体和联合体。例如,当我们需要定义一个学生的信息时,可以使用结构体:

struct student {
   char name[20];
   int age;
   float gpa;
};

当我们需要处理一个字节流时,可以使用联合体:

union byte_stream {
   unsigned char bytes[4];
   float value;
};

由于联合体的特殊性,我们需要特别小心,避免出现不可预知的结果。因此,在使用联合体时,要尽量避免修改一个成员变量,同时使用时要小心谨慎。

总结

结构体和联合体是C语言中两种常用的复合数据类型,可以将多个变量结合在一起,形成一个新的数据类型。结构体和联合体的定义语法比较类似,但是它们有着不同的特点和用法。结构体适合处理多个不同的信息,联合体适合处理一段内存上的不同表示方式。使用结构体和联合体时,需要注意它们的定义和使用方法,避免出现不可预知的结果。