C 语言编程教程

C 语言 - 首页

C 语言基础

C 语言 - 概述 C 语言 - 特性 C 语言 - 发展历史 C 语言 - 环境设置 C 语言 - 程序结构 C 语言 - Hello World C - 编译过程 C - 注释 C - 标记 C - 关键字 C - 标识符 C - 用户输入 C - 基本语法 C - 数据类型 C - 变量 C - 整数提升 C - 类型转换 C - 类型转换 C - 布尔值

C 语言中的常量和文字

C - 常量 C - 字面量 C - 转义序列 C - 格式说明符

C 语言中的运算符

C - 运算符 C - 算术运算符 C - 关系运算符 C - 逻辑运算符 C - 位运算符 C - 赋值运算符 C - 一元运算符 C - 递增和递减运算符 C - 三元运算符 C - sizeof 运算符 C - 运算符优先级 C - 其他运算符

C 语言中的决策

C - 决策 C - if 语句 C - if...else 语句 C - 嵌套 if 语句 C - switch 语句 C - 嵌套 switch 语句

C 语言中的循环

C - 循环 C - While 循环 C - For 循环 C - Do...while 循环 C - 嵌套循环 C - 无限循环 C - Break 语句 C - Continue 语句 C - goto 语句

C 语言中的函数

C - 函数 C - Main 函数 C - 按值调用函数 C - 按引用调用函数 C - 嵌套函数 C - 可变参数函数 C - 用户定义函数 C - 回调函数 C - return 语句 C - 递归

C 语言中的作用域规则

C - 作用域规则 C - 静态变量 C - 全局变量

C 语言中的数组

C - 数组 C - 数组的属性 C - 多维数组 C - 将数组传递给函数 C - 从函数返回数组 C - 可变长度数组

C 语言中的指针

C - 指针 C - 指针和数组 C - 指针的应用 C - 指针运算 C - 指针数组 C - 指向指针的指针 C - 将指针传递给函数 C - 从函数返回指针 C - 函数指针 C - 指向数组的指针 C - 指向结构体的指针 C - 指针链 C - 指针 vs 数组 C - 字符指针和函数 C - NULL 指针 C - void 指针 C - 悬垂指针 C - 解引用指针 C - Near、Far 和 Huge 指针 C - 指针数组的初始化 C - 指针与多维数组

C 语言中的字符串

C - 字符串 C - 字符串数组 C - 特殊字符

C 语言的结构体和联合

C - 结构体 C - 结构体和函数 C - 结构体数组 C - 自引用结构 C - 查找表 C - 点 (.) 运算符 C - 枚举(或 enum) C - 结构填充和打包 C - 嵌套结构 C - 匿名结构和联合 C - 联合 C - Bit 位字段 C - Typedef

C 语言中的文件处理

C - 输入和输出 C - 文件 I/O(文件处理)

C 语言中的预处理器

C - 预处理器 C - #pragma 编译指示 C - 预处理器操作符 C - 宏 C - 头文件

C 语言中的内存管理

C - 内存管理 C - 内存地址 C - 存储类

C 其他主题

C - 错误处理 C - 可变参数 C - 命令执行 C - 数学函数 C - static 静态关键字 C - 随机数生成 C - 命令行参数

C 语言编程资源

C语言问题与解答答案 C语言快速指南 C语言速查表 C语言实用资源 C语言讨论


C 语言中的联合

联合是 C 语言中一种特殊的数据类型,允许在同一内存位置存储不同的数据类型。您可以定义一个包含多个成员的联合,但在任何给定时刻只有一个成员可以包含值。联合提供了一种高效的方式,可以将同一内存位置用于多种用途。

联合的所有成员共享同一内存位置。因此,如果需要为两个或多个成员使用同一内存位置,那么联合是最佳的数据类型。最大的联合成员决定了联合的大小。

定义联合

联合变量的创建方式与结构体变量相同。关键字 union 用于在 C 语言中定义联合。

语法

以下是在 C 语言中定义 联合 的语法 -

union [union tag]{
   member definition;
   member definition;
   ...
   member definition;
} [one or more union variables];  

"联合标签"是可选的,每个成员定义都是一个普通的变量定义,例如"int i;"或"float f;"或其他任何有效的变量定义。

在联合定义的末尾,在最后一个分号之前,可以指定一个或多个联合变量。

访问联合成员

要访问联合的任何成员,我们使用成员访问运算符 (.)。成员访问运算符的代码形式为联合变量名和我们要访问的联合成员之间的一个句点。您可以使用关键字 union 来定义联合类型的变量。

语法

以下是使用 C 语言访问联合成员的语法 -

union_name.member_name;

联合成员的初始化

您可以使用赋值运算符 (=) 为联合成员赋值来初始化它们。

语法

以下是初始化联合成员的语法 -

union_variable.member_name = value;

示例

以下代码语句演示了如何初始化联合"data"的成员"i" -

data.i = 10;

联合示例

示例 1

以下示例演示了如何在程序中使用联合 -

#include <stdio.h>
#include <string.h>

union Data{
   int i;
   float f;
   char str[20];
};

int main(){
   union Data data;        
   
   data.i = 10;
   data.f = 220.5;
   strcpy(data.str, "C Programming");
   
   printf("data.i: %d 
", data.i);
   printf("data.f: %f 
", data.f);
   printf("data.str: %s 
", data.str); 
   return 0;
}

输出

当编译并执行上述代码时,它会产生以下结果 -

data.i: 1917853763 
data.f: 4122360580327794860452759994368.000000 
data.str: C Programming

这里,我们可以看到 if(联合体成员)的值显示为垃圾值,因为赋给变量的最终值已经占用了内存位置,这也是 str 成员的值打印效果很好的原因。

示例 2

现在让我们再次看一下同一个例子,我们将一次使用一个变量,这也是使用联合体的主要目的 -

#include <stdio.h>
#include <string.h>

union Data{
   int i;
   float f;
   char str[20];
};

int main(){
   
   union Data data;        
   
   data.i = 10;
   printf("data.i: %d 
", data.i);
   
   data.f = 220.5;
   printf("data.f: %f 
", data.f);
   
   strcpy(data.str, "C Programming");
   printf("data.str: %s 
", data.str);
   return 0;
}

输出

当编译并执行上述代码时,它会产生以下结果 -

data.i: 10 
data.f: 220.500000 
data.str: C Programming

这里,所有联合成员的值都打印得很好,因为每次只使用一个成员。

联合的大小

联合的大小是其最大成员的大小。例如,如果一个联合包含两个 charint 类型的成员。在这种情况下,联合的大小将是 int 的大小,因为 int 是最大的成员。

您可以使用 sizeof() 运算符 来获取联合的大小。

示例

在以下示例中,我们将打印联合的大小 -

#include <stdio.h>

// 定义一个联合
union Data {
   int a;
   float b;
   char c[20];
};

int main() {
   union Data data;

   // 打印联合体每个成员的大小
   printf("Size of a: %lu bytes
", sizeof(data.a));
   printf("Size of b: %lu bytes
", sizeof(data.b));
   printf("Size of c: %lu bytes
", sizeof(data.c));

   // 打印联合的大小
   printf("Size of union: %lu bytes
", sizeof(data));

   return 0;
}

输出

当您编译并执行代码时,它将产生以下输出 -

Size of a: 4 bytes
Size of b: 4 bytes
Size of c: 20 bytes
Size of union: 20 bytes

结构体与联合体的区别

结构体和联合体都是 C 语言编程中的复合数据类型。结构体和联合体之间最显著的区别在于它们存储数据的方式。结构体将每个成员存储在单独的内存位置,而联合体将所有成员存储在相同的内存位置。

以下是名为 myunion 的联合体类型的定义 -

union myunion{ 
   int a;
   double b;
   char c;
};

联合的定义类似于结构体的定义。具有相同元素的"struct type mystruct"的定义如下所示 -

struct mystruct{
   int a;
   double b;
   char c;
};

结构体和联合体之间的主要区别在于变量的大小。编译器会为结构体变量分配内存,以便存储所有元素的值。mystruct 包含三个元素:int、double 和 char,共占用 13 个字节(4 + 8 + 1)。因此,sizeof(struct mystruct) 返回 13。

另一方面,对于联合类型变量,编译器会分配一块大小足以容纳最大字节大小元素的内存。myunion 类型包含一个 int、一个 double 和一个 char 元素。在这三个元素中,double 变量的大小最大,为 8。因此,sizeof(union myunion) 返回 8。

另外需要考虑的一点是,联合变量只能保存其一个元素的值。当你为一个元素赋值时,其他元素是未定义的。如果你尝试使用其他元素,将会导致一些垃圾。

示例 1:联合占用的内存

在下面的代码中,我们定义了一个名为 Data 的联合类型,它包含三个成员 ifstrData 类型的变量可以存储整数、浮点数或字符串。这意味着一个变量(即相同的内存位置)可以用来存储多种类型的数据。你可以根据需要在联合中使用任何内置或用户定义的数据类型。

联合占用的内存足够大,可以容纳联合中最大的成员。例如,在上面的例子中,Data将占用20个字节的内存空间,因为这是字符串可以占用的最大空间。

以下示例显示上述联合体占用的总内存大小 -

#include <stdio.h>
#include <string.h>

union Data{
   int i;
   float f;
   char str[20];
};

int main(){
   union Data data;        
   printf("Memory occupied by Union Data: %d 
", sizeof(data));
   return 0;
}

输出

当您编译并执行代码时,它将产生以下输出 -

Memory occupied by Union Data: 20

示例 2:结构体占用的内存

现在,让我们创建一个具有相同元素的结构体,并检查它在内存中占用了多少空间。

#include <stdio.h>
#include <string.h>

struct Data{
   int i;
   float f;
   char str[20];
};

int main(){
   struct Data data;        
   printf("Memory occupied by Struct Data: %d 
", sizeof(data));
   return 0;
}

输出

此结构将占用 28 个字节(4 + 4 + 20)。运行代码并检查其输出 -

Memory occupied by Struct Data: 28