成长之路---C语言笔记(结构体与共用体)

简介: 成长之路---C语言笔记(结构体与共用体)

谚云:世上无难事,只畏有心人,有心之人,即立志之坚午也,志坚则不畏事之不成---任弼时


在实际问题中,一组数据往往具有不同的数据类型。显然不能用一个数组来存放这一组数据,为了整体存放这些类型不同的相关数据,C语言允许用户自定义的数据类型包括结构体类型、共用体类型和枚举类型,其中结构体和共用体属于构造类型,枚举型属于简单类型。


结构体


C语言中给出了一种构造数据类型——结构(struct)或叫结构体, 它相当于其他高级语言中的记录。结构体是一种构造类型, 它由若干数据项组成,组成结构体的各个数据项被称为结构体成员,每一个成员可以是一个基本数据类型或者一个构造类型。结构体既然是一种“构造”而成的数据类型,那么在说明和使用之前必须先根据实际情况定义结构体类型,然后再定义结构体类型变量,如同在说明和调用函数之前要先定义函数一样。


结构体类型的定义


因为结构体类型比较复杂系统无法事先为用户定义一种统一的结构体类型因此在我们定义结构体变量之前,用户要先定义结构体类型,即用自己定义的结构体类型定义结构体变量。在定义结构体类型过程中我们应该指明该结构体的类型名,包含哪些成员,各成员及其数据类型。


struct 结构体名
{
成员列表;
};//末尾的分号一定要加分号


结构体名用作结构体类型的标志,又被称作"结构体标志(Structure Tag)".成员列表由诺诺干个成员组成,每个成员都是该结构体的一个组成部分,每个成员都是该结构体的一个组成部分,对每个成员也必须作类型说明。


struct 结构体类型名
{
类型说明符 成员1;
类型说明符 成员2;
类型说明符 成员3;
};


注:


struet 是关键字,必须原样写出,表示定义一个结构体类型,它是语句的主体。


结构体名、成员名的命名规则与标识符的定义规则一样。大括号内是结构体成员列表,各结构体成员的定义方式和一般变量的定义方式相同。


结构体类型的定义是一个语句, 应以分号结束。注意,“}”后面的分号一定不能省略,否则会出错。


结构体类型的定义只说明了该类型的构成形式,系统并不为其分配内存空间,编译系统仅给变量分配内存空间。


结构体成员的类型也可以是另一个结构体类型(嵌套使用)遵循先定义后使用原则。


”struct 结构体类型名” 为结构体的类型说明符, 可用于定义或说明变量。 结构体类型的定义可置于函数内,这样该类型名的作用域仅为该函数。如果结构体类型的定义位于函数之外,则其定义为全局的,可在整个程序中使用。


结构体是一种复杂的数据类型,是数目固定、类型不同的变量在内存中的分配模式,并没有分配实际的内存空间。当定义了结构体类型的变量之后,系统才能在内存中为变量分配存储空间。因此,结构体类型定义是为结构体变量的定义服务的。


结构体变量的定义


结构体类型反映的是所处理对象的抽象特征,如要描述具体对象时,就需要定义结构体类型的变量,简称为结构体变量或结构体。定义结构体变量有三种方法。


定义类型后再定义变量


/*结构体类型名 变量1,变量2,...变量n;*/
例如:
struct stu
{
int b;
char c;
};
struct stu a;


定义结构体类型的同时定义结构体变量


/*struct 结构体名
{
成员列表;
}变量名列表;*/
//例如:
struct stu
{
int b;
int c;
}a,d;


直接定义结构体变量


/*struct
{
成员列表;
}变量名列表;*/
//例如:
struct 
{
int a;
char b;
}a,b;


注:此方法没有具体指出结构体类型名,所以在程序中仅有-处需 要定义某种结构体类型变量时可使用,该方法与前两种方法的区别在于,第三种方法省去了结构体类型名,而直接给出结构体变量,这种情况下不能使用前两种方法对变量进行定义,只能在构造类型的时候定义变量。


结构体变量的引用


在程序中使用结构体变量时,要对每个单元格进行引用,即不能把它作为个整体来使用。除了允许具有相同类型的结构体变量相互赋值以外,一般对结构体变量的使用,包括赋值、输入、输出、运算等都是通过结构体变量的成员来实现的。


结构体变量名.成员名


在之前的学习中我们了解过运算符“.”(成员运算符),其优先级最高,结合方向从左向右。


如果成员本身是一个结构体变量,则必须逐级找到最低级的成员才能使用,即只能对最低级的成员进行赋值或存取以及运算。成员可以在程序中单独使用,与普通变量完全相同。 其中,“.”运算符的优先级别最高,所以可以把“结构体变量名成员名”看作一个整体。如果a、b是同类型变量, 则对于各自的同名成员 num,也可用a.num、 b.num来区分。对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定进行的运算)


可以引用结构体变量成员的地址,也可以引用结构体变量的地址。结构体变量的地址的主要用作函数参数,传递结构体变量的地址。


结构体变量的赋值


已知结构体变量的值,在定义结构体变量时可以给它的成员赋初值,这就是结构体的初始化,它包括定义结构体变量时赋初值和定义结构体变量后赋初值。


定义结构体变量时赋初值 和其他类型变量一样,对于结构体变量可以在定义时进行初始化赋值。对结构体变量赋初值的格式为:


struct结构体类型名变量名={成员1的值,成员2的值,..成员n的值};


初值表用“{}”括起来,表中各个数据以逗号分隔,并且应与结构体类型定义时的成员个数相等,类型一致。如果初值个数少于结构体成员个数,则给无初值对应的成员赋予0值;如果初值个数多于结构体成员个数时,则编译出错。当结构体具有嵌套结构时,内层结构体的初值也需用“{}”括起来。案例:


#include <stdio.h>
int main()
{
    struct stu
    {
        int num;
        char name[20];
        char sex;
        float score;
    }a = { 1001, "Zhang", 'M',78.5 };
    /*定义结构体变量并初始化*/
    struct stu b = { 1002,"Wang", 'F',67.5 };
    printf("NO.=%d\tName= =%s\tsex=%c\tscore=%5.2f\n", a.num, a.name, a.sex, a.score);
    /*输出结构体a的值*/
    printf("NO.=%d\tName= -%s\tsex=%c\tscore- =%5.2f", b.num, b.name, b.sex, b.score);
    /*输出结构体b的值*/
}

0c0044e4b8a5066802338b9bc581d4b7_2342ec653d2271ae689e53b041e72c71.png


定义结构体后赋初值


#include<stdio.h>
#include<string.h>
struct stu
{
    int num;
   char name[20];
   char sex;
   float score;
}a;
void main()
{
    struct stu b;
    a.num = 601001;
    printf("输入姓名: ");
    fgets(a.name,10,stdin);
    a.sex = 'M';
    a.score - 76.5;
    b = a;
   /* 将结构体变量a赋值给结构体变量b */
    printf("No.=%d\tName=%s\tsex=%c\tscore=%5.2f\n", a.num, a.name, a.sex, a.score);
    printf("No.=%d\tName=%s\tsex=%c\tscore-%5.2f\n", b.num, b.name, b.sex, b.score);
}


5eef6f7ff3d7aaf5ebc68901816c353f_81685479c45ceb130dda06e0d5b1e84d.png


注:对于结构体变量各个成员不能一次性全部赋值,但是对于同类型的结构体变量之间可以整体赋值一次。


共用体


为了节省内存空间,我们可以把不同用途的数据存放在同一个存储区域,这种数据类型称为共用体类型,也称为联合体类型(union)。构成共用体变量的各成员项的数据类型可以是相同的,也可以是不同的。共用体类型和共用体变量的定义方式与结构体的定义方法类似,也需要先构造共用体类型,后定义共用体变量。共用体成员的引用也与结构体成员的引用方法类似。二者主要区别在于对成员项的存储方式。


共用体的定义


我们可以先定义共用体类型,然后用已定义的共用体类型定义共用体变量;也可以把共用体类型和共用体变量放在一个语句中一次定义。


union {成员列表;};


注:和结构体类型定义一样,在没有定义共用体变量之前,共用体类型定义只是说明了共用体变量使用的内存模式,并没有分配具体的存储空间。 括号后的分号是不可缺少的。这与结构体类型定义是类似的,凡说明为共用体类型num的变量都由上述两个成员组成。


共用体类型变量的定义


与结构体类型变量的定义相似,共用体类型变量的定义也有三种形式。


union mun
{
char b;
int c;
}a;


注::结构体类型的变量所占空间为各个成员项所占空间的总和,而共用体类型的变量所占空间是以最大长度成员项所占空间的大小为准。


共用体类型变量的引用


共用体变量名.成员名


诺引用共用体成员,则a.x即是共用体类型变量a的成员x的值,a.y即是共用体类型变量a的成员y的值。


共用体类型变量的初始化


union 共用体类型名 共用体变量名={初始值};
union num a={45};


使用例子


#include<stdio.h>
union num
{
    short x;float y;
};
int main()
{
    union num a;
    printf("输入x: \n");
    scanf("%d", &a.x);
    printf("a.x=%d\n", a.x);
    printf("输入y: \n");
    scanf("%f", &a.y);
    printf("a.y=%f\n", a.y);
    printf("a.x=%d\n", a.x);
}


8bbd8f6bac2a3da9f2f1b836a1e490c5_d62bfb5ff216a94daf7f1512ed437277.png


今日题目


输⼊两个⾮负 10 进制整数 A 和 B (≤230−1),输出 A+B 的 D (1<D≤10)进制数 输⼊: m n f (解释:f是进制数) 123 456 8 输出: 1103


答案及解题思路见下方,欢迎讨论。


最后的话 :如果大家觉得这篇文章对你们有帮助的话希望你们能够点点关注,你们的关注是我继续写下去的动力,谢谢大家。



答案及解析、


思路:先求和,然后一直取余就行了。最后倒着输出


#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
    int number_a = 0, number_b = 0, number_c = 0, sum = 0, count = 0;
    int p[100] = { 0 };
    scanf("%d %d %d", &number_a, &number_b, &number_c);
    sum = number_a + number_b;//求和
    while (sum) {
        p[count++] = sum % number_c;//取余
        sum = sum / number_c;
    }
    for (int i = count - 1;i >= 0;i--) {//倒着输出
        printf("%d", p[i]);
    }
    if (count == 0) printf("0");//如果sum为0输出0
    return 0;
}
目录
相关文章
|
9月前
|
存储 网络协议 编译器
【C语言】深入解析C语言结构体:定义、声明与高级应用实践
通过根据需求合理选择结构体定义和声明的放置位置,并灵活结合动态内存分配、内存优化和数据结构设计,可以显著提高代码的可维护性和运行效率。在实际开发中,建议遵循以下原则: - **模块化设计**:尽可能封装实现细节,减少模块间的耦合。 - **内存管理**:明确动态分配与释放的责任,防止资源泄漏。 - **优化顺序**:合理排列结构体成员以减少内存占用。
685 14
|
9月前
|
存储 编译器 C语言
【C语言】结构体详解 -《探索C语言的 “小宇宙” 》
结构体通过`struct`关键字定义。定义结构体时,需要指定结构体的名称以及结构体内部的成员变量。
452 10
|
10月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
864 13
|
10月前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
322 12
|
10月前
|
存储 数据建模 程序员
C 语言结构体 —— 数据封装的利器
C语言结构体是一种用户自定义的数据类型,用于将不同类型的数据组合在一起,形成一个整体。它支持数据封装,便于管理和传递复杂数据,是程序设计中的重要工具。
|
10月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
197 4
|
11月前
|
存储 C语言
如何在 C 语言中实现结构体的深拷贝
在C语言中实现结构体的深拷贝,需要手动分配内存并逐个复制成员变量,确保新结构体与原结构体完全独立,避免浅拷贝导致的数据共享问题。具体方法包括使用 `malloc` 分配内存和 `memcpy` 或手动赋值。
346 10
|
11月前
|
存储 大数据 编译器
C语言:结构体对齐规则
C语言中,结构体对齐规则是指编译器为了提高数据访问效率,会根据成员变量的类型对结构体中的成员进行内存对齐。通常遵循编译器默认的对齐方式或使用特定的对齐指令来优化结构体布局,以减少内存浪费并提升性能。
|
11月前
|
编译器 C语言
共用体和结构体在 C 语言中的优先级是怎样的
在C语言中,共用体(union)和结构体(struct)的优先级相同,它们都是用户自定义的数据类型,用于组合不同类型的数据。但是,共用体中的所有成员共享同一段内存,而结构体中的成员各自占用独立的内存空间。
|
11月前
|
存储 C语言
C语言:结构体与共用体的区别
C语言中,结构体(struct)和共用体(union)都用于组合不同类型的数据,但使用方式不同。结构体为每个成员分配独立的内存空间,而共用体的所有成员共享同一段内存,节省空间但需谨慎使用。