10.结构体、共用体、枚举

news2024/12/28 17:35:50

头文件:#include<string.h>

结构体定义
//struct:结构体关键字
//stu:结构体类型名,指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元

//使用结构体类型必须是struct stu
//num name age叫做结构体中的成员
//定义结构体类型的时候不要给成员赋值(重要)
//定义结构体类型的时候 并没有分配空间 所以不能给成员赋值       

struct stu 
{
    int num;
    char name[32];
    int age;
};        //一定要记得有;号

结构体中的成员拥有独立的空间

结构体独立空间

知识点二:结构体变量的定义

struct stu
{
    int num;	//4B
    char name [32];//32B
    int age;	//4B
};

void test1(void)
{
    //就用结构体类型定义一个变量
    struct stu lucy;	//lucy 是局部变量 lucy的成员内容不确定
    //通过结构体变量访问结构体中的成员(访问时一定要遵循成员自身的类型)
    lucy.num = 100;
    strcpy (lucy.name,"德玛西亚");
    lucy.age = 18;

    printf("num = %d\n",lucy.num);
    printf("name = %s\n",lucy.name);
    printf("age = %d\n",lucy.age);
}

知识点三:结构体变量的初始化

struct stu
{
    int num;		//4B
    char name [32];	//32B
    int age;		//4B
};

void test1(void)
{
    //初始化的顺序必 须和 结构体成员的顺序一致
    struct stu lucy = {100,"德玛西亚",18};
    printf(" num = %d,name = %s,age = %d\n", lucy.num,lucy.name,lucy.age);
    //清空结构体变量
    memset(&lucy,0,sizeof(lucy));
}

知识点四:结构体变量获取键盘输入

struct stu
{
    int num;		//4B
    char name [32];	//32B
    int age;		//4B
};
void test1(void)
{
    struct stu lucy;
    memset(&lucy,0,sizeof(lucy));
    printf("请输入num name_age:") ;
    //&lucy.num取的是num成员地址
    scanf("%d %s %d",&lucy.num,&lucy.name,&lucy.age);
    printf("num = %d,name = %s,age = %d\n",lucy.num,lucy.name,lucy.age);
}

知识点五:结构体变量之间的赋值

内存拷贝

memcpy:内存块中的数据从一个地方复制到另一个地方

memcpy(void *str1, const void *str2, size_t n);
参数说明:
    str1:指向用于存储复制内容的目标数组,类型强制转换为 void* 指针
    str2:指向要复制的数据源,类型强制转换为 void* 指针
    n:要被复制的字节数
struct stu
{
    int num;		//4B
    char name [32];	//32B
    int age;		//4B
};
void test1(void)
{
    struct stu lucy = {100,"小法",18} ;
    struct stu bob;
    //需求将lucy的值赋值bob
    //方式一:逐个成员赋值
    //bob.num = lucy.num;
    //strcpy(bob.name,lucy.name);
    //bob.age = lucy.age;
    //方拾二:相同类型的结构体变量 可以直接赋值(推荐)
    //bob = lucy;    
    //方法三:方法二的底层实现
    memcpy(&bob, &lucy,sizeof(struct stu));
    printf("num = %d,name = %s,age = %d\n",bob.num,bob.name,bob.age);
}

知识点六:结构体数值

结构体数值
struct stu
{
    int num;		//4B
    char name [32];	//32B
    int age;		//4B
};
void test1(void)
{
    struct stu arr[5]={
        {100,"小法",18},
        {101,"德玛西亚",19},
        {102,"盲僧",20},
        {103,"快乐风男",30},{104,"提莫",8}};
    int n = sizeof(arr)/sizeof(arr[0]);
    int i = 0;
    for(i = 0;i < n;i++)
    {
        printf("num = %d,name = %s,age = %d\n",arr[i].num, arr[i].name,arr[i].age);
    }
}

知识点七:冒泡排序

冒泡排序
#include<stdio.h>
#include<stdlib.h>
void test1(void)
{
    int n = 0;
    int i,j = 0;
    int *arr = NULL;
    printf("请输入数据的个数:");
    scanf ("%d",&n);
    //根据元素的个数申请空间
    arr = (int *)calloc(n,sizeof(int));
    if(NULL == arr)
    {
        perror("calloc");
        return;
    }
     //键盘给动态数组获取输入
    printf("请输入%d个int数据\n",n);
    for(i = 0;i < n;i++)
    {
        scanf("%d",arr+i);//arr+i 第i个元素的地址
    }
    //排序
    for(i = 0;i < n-1;i++)
    {
        for(j = 0; j < n-i-1;j++)
        {
            if(arr[j] > arr[j+1])    //从小到大排列 
            {
                int tmp = 0;
                tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }            
        }        
    }
    //数组的遍历
    for(i = 0;i < n; i++)
    {
        printf("%d ",arr[i]);        
    }
    printf("\n");
    //释放空间
    if(arr != NULL)
    {
        free(arr) ;
        arr = NULL;
    }
}

升级版

#include<stdio.h>
#include<stdlib.h>
void test1(void)
{
    int n = 0;
    int i,j = 0;
    int *arr = NULL;
    printf("请输入数据的个数:");
    scanf ("%d",&n);
    //根据元素的个数申请空间
    arr = (int *)calloc(n,sizeof(int));
    if(NULL == arr)
    {
        perror("calloc");
        return;
    }
     //键盘给动态数组获取输入
    printf("请输入%d个int数据\n",n);
    for(i = 0;i < n;i++)
    {
        scanf("%d",arr+i);	//arr+i 第i个元素的地址
    }
    //排序
    for(i = 0;i < n-1;i++)
    {
        int flag = 0; 
        for(j = 0; j < n-i-1; j++)
        {
            if(arr[j] > arr[j+1])    //从小到大排列 
            {
                int tmp = 0;
                tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }            
        }
        if(flag == 0)    //数组已经有序 
        break;        
    }
    //数组的遍历
    for(i = 0;i < n; i++)
    {
        printf("%d ",arr[i]);        
    }
    printf("\n");
    //释放空间
    if(arr != NULL)
    {
        free(arr);
        arr = NULL;
    }    
}

结构体数组排序

#include<stdio.h>
#include<string.h>
struct stu
{
    int num;		//4B
    char name [32];	//32B
    int age;		//4B
};

void test1(void)
{
    struct stu arr[5];
    int i,j = 0;
    int n = sizeof (arr)/sizeof(arr[0]);
    memset (arr,0,sizeof(arr));		//整个数组清0
    //获取键盘输入
    printf("请输入%d个学生信息\n",n) ;
    for(i=0;i<n; i++)
    {
        scanf("%d %s %d",&arr[i].num,arr[i].name,&arr[i].age);
    }
    //根据学号排序
    for(i = 0;i < n-1;i++)
    {
        for(j = 0; j < n-i-1;j++)
        {
            if(arr[j].num < arr[ j+1].num) //按照num的从大到小排序
            {
                struct stu tmp;
                tmp = arr[j] ;
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }        
    }
    //遍 历
    printf("--------------\n") ;
    for(i = 0;i < n;i++)
    {
        printf("%d %s %d\n",arr[i].num,arr[i].name,arr[i].age);
    }
}

知识点八:typedef 给已有的类型取个别名

1、给int取个别名INT32

#include<stdio.h>
// typedef使用步骤:
//1、先用已有的类型_ 定义一个变量      int num;
//2、用别名替换变量名            	int INT32;
//3、在整个表达式前添加typedef        typedef int INT32;
//注意:不能创造新的类型
typedef int INT32;
void test1()
{
    INT32 num = 10;
    printf("num = %d\n",num);//10
}

2、给数组取个别名

//ARR_TYPE 就是数组类型,该数组必须有5个元素 每个元素为int
typedef int ARR_TYPE[5];
void test1()
{
    ARR_TYPE arr = {10, 20, 30, 40, 50}; //arr就是一个拥有5个元素每个元素为int的数
    int i = 0;
    for(i = 0;i < 5;i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n") ;
}

3、给指针取别名

typedef int *P_TYPE;
void test1()
{
    int num = 10;
    P_TYPE p = &num;    //P_TYPE p == int *p
    printf("*p = %d\n", *p);	//10 
}

4、给函数指针取别名

int my_add(int x,int y)
{
    return x+y;
}
//FUN_P是一个函数指针类型 该函数必须有两个int形参以及一个int返回值
typedef int (*FUN_P)(int x, int y);
void test1()
{
    FUN_P p = my_add;
    printf("%d\n",p(100,200));    //300;
}

5、给结构体类型取个别名

typedef struct stu
{
    int num;
    char name[32];
    int age;
}STU;    //STU == struct stu
void test1()
{
    STU lucy = {100,"lucy",18};
}

知识点九:结构体指针

结构体指针
typedef struct stu
{
    int num;
    char name[16];
    int age;
}STU;    //STU是结构体类型
void test1()
{
    STU lucy = {100,"lucy",18};
    STU *p = &lucy;
    printf("num = %d,name = %s,age = %d\n",lucy.num,lucy.name,lucy.age);
    //注意:如果是结构体指针需要用下面两种方式输出
    printf("num = %d,name = %s,age = %d\n",(*p).num,(*p).name,(*p).age);
    printf("num = %d,name = %s,age = %d\n",p->num,p->name,p->age);
    printf("num = %d\n",(&lucy)->num);
}

知识点十:结构体指针作为函数的参数

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

typedef struct stu
{
    int num;
    char name[16];
    int age;
}STU;    //STU是结构体类型
void mySetSTUData(STU *p)	//p=&lucy
{
    printf("请输入一个学生的信息num name age\n");
    scanf("%d %s %d",&p->num,p->name,&p->age);
    return;
}
void myPrintSTUData(const STU *p)	//tmp =lucy    *p只读 
{
    //constSTU*p不允许用户借助p修改 p所指向的空间内容
    printf("num = %d,name = %s,age = %d\n",p->num,p->name,p->age);
}
void test1()
{
    STU lucy;
    memset(&lucy,0,sizeof(lucy));
    //定义一个函数给lucy的成员获取键盘输入
    mySetSTUData(&lucy);
    //定义一个函数 打印lucy的成员信息
    myPrintSTUData(&lucy);    
}

知识点十一:结构体内存对齐

结构体内存对齐

对齐规则:

对齐规则
struct data 
{
    char c;	// 1B
    int i;	//4B
};
void test1()
{    
    //结构体的大小>=成员大小之和
    printf("%d\n",sizeof(struct data));	//8
    struct data d;
    printf("&d.c = %u\n",&d.c);
    printf("&d.i = %u\n",&d.i);
}

知识点十二:结构体嵌套结构体

结构体嵌套结构体
typedef struct
{
    int x;
    int y;
}DATA2;
typedef struct
{
    int a;
    int b;
    DATA2 c;	//结构体变量c作为了DATA3的成员叫结构体嵌套结构体
}DATA3;
void test1()
{    
    //DATA3 data = {10, 20, 30, 40};
    DATA3 data = {10,20, {30,40}};	//推荐
    printf("a = %d\n",data.a);
    printf("b = %d\n",data.b);
    printf("x = %d\n",data.c.x);    //访问最底层 
    printf("y = %d\n",data.c.y);
}

知识点十三:结构体嵌套结构体的内存对齐

内存对齐
typedef struct
{
    short d;
    char e;
}DATA2;
typedef struct
{
    short a;
    int b;
    DATA2 c;
    char f;
}DATA;
void test1()
{    
    printf("%d\n", sizeof(DATA));
    DATA data;
    printf ("a:%u\n",&data.a);
    printf("b:%u\n",&data.b);
    printf("c中d: %u\n",&data.c.d);
    printf("c中e: %u\n", &data.c.e);
    printf("f:%u\n",&data.f);
}

知识点十四:指定对齐原则

1、使用#pragmapack改变默认对其原则

格式:#pragma pack (value) 时的指定对齐值value

注意:

     1)value只能是:1248等

     2)指定对齐值与数据类型对齐值相比取较小值

     如:如果指定对齐值:

          设为1:则short、 int、 float等均为1

          设为2:则char仍为1,short为2,int变为2

步骤:

     1)确定分单位:每一 -行应该分配的字节数,min(value,默认分配单位)

     2)成员偏移量=成员自身类型的整数(0~n)倍

     3)收尾工作=分配单位的整数(0~n) 倍

//指定对齐规则
#pragma pack(2)
typedef struct
{
    char a;
    int b;
    short C;
}DATA1;

void test1()
{    
    printf ("%d\n",sizeof(DATA1));    //8
    return;
}

知识点十五:位段

位段

位段的使用

//位段 一般只考虑unsigned int类型也可以考虑unsi gned char
typedef struct
{
    unsigned char a:2;	//a只占一个字节中的两位二进制位
    unsigned char b:2;	//b只占一个字节中的两位二进制位
    //相邻位域可以压缩( 压缩的位数 不能超过  成员自身大小)
    unsigned char c:5;
}DATA2;
void test1()
{    
    printf ("%d\n",sizeof(DATA2));	//2
    DATA2 data;
    //位段不能取地址
    //printf("%p\n",&data.a);
    //位段的赋值不要操作位段的大小a:2
    data.a = 6;    //0110
    printf("%u\n",data.a);    //2
    return;
}

无意义位段

无意义位段
typedef struct
{
    unsigned char a:2;	//00
    unsigned char :4;	//无意 义的位段( 占有两位)
    unsigned char b:2;	//1 1
}DATA3;

void test1()
{    
    DATA3 data;
    memset (&data,0,1);
    data.a = 0;    //00
    data.b = 3;    //11
    printf("%d\n", sizeof(DATA3));
    printf("%#x\n",*(unsigned char *)&data);    //1100 0000/ /0xc0  a是高位,b是低位
    return;
}

应用场景

应用场景

另起一个位段

另起一个位段
typedef struct
{
    unsigned char a:2;   //00
    unsigned char :0;    //另起一个位段
    unsigned char b:2;   //11
}DATA4;
void test1()
{    
    printf ("%d\n",sizeof(DATA4));
    return;
}

知识点十六:共用体与结构体的区别

结构体:struct

所有的成员拥有独立的空间

共用体与结构体的区别
struct stu
{
    char a;
    short b;
    int C;
};	// a  b  c成员有用独立的空间

共用体(联合体)union

所有的成员共享同一份空间

共用体与结构体的区别1
struct stu
{
    char a;
    short b;
    int c;
};	// a  b  c成员有用共享一份空间

知识点十七:共用体

union data
{
    char a;
    short b;
    int c;
};
void test1()
{    
    printf("%d\n",sizeof(union data));	//4
    union data A;
    A.a = 10;
    A.b = 20;
    A.c = 30;
    printf("%d\n",A.a + A.b + A.c);    //90
}

共用体虽然共有同一份空间但是从空间读取的字节数是有成员自身类型决定

共用体1 共用体2
union data
{
    char a;
    short b;
    int c;
};
void test1()
{    
    printf("%d\n", sizeof(union data));	//4
    union data A;
    A.c = 0x01020304;
    A.b = 0x0102;
    A.a = 0x01;
    printf("%#x\n",A.a+A.b+A.c);    
}

知识点十八:枚举

枚举

     将变量的值一一列举出来,变量的值只限于列举出来的值的范围内

枚举类型定义:

enum 枚举名
{
    枚举值表
};

在枚举值表中应列出所有可用值,也称为枚举元素,枚举变量仅能取枚举值所列元素

//枚举列表的值:默认从0开始
enum POKER {HONGTAO,HEITAO=30,MEIHUA=40,FANGKUAI};
void test1()
{    
    //poker_ color的取值为HONGTAO,HEITAO, MEIHUA, FANGKUAI中某一个
    enum POKER poker_color = HEITAO;
    printf("poker_ olor = %d\n",poker_color);    //30
    printf("HONGTAO = %d\n",HONGTAO);   //0
    printf("HEITAO = %d\n",HEITAO);    	//30
    printf("MEIHUA = %d\n",MEIHUA);    	//40
    printf("FANGKUAI = %d\n",FANGKUAI); //41
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1808086.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CDR2024软件破解Keygen激活工具2024最新版

CorelDRAW Graphics Suite2024最新版&#xff0c;这是一款让我爱不释手的图形设计神器&#xff01;作为一个软件评测专家&#xff0c;我一直在寻找一款能够提升我的设计效率和创造力的工具。而这款软件&#xff0c;简直就是为我量身定制的&#xff01;&#x1f389; 「CorelDR…

北航第五次数据结构与程序设计编程题复习

北航第五次数据结构与程序设计编程题复习 树叶节点遍历&#xff08;树-基础题&#xff09;计算器&#xff08;表达式计算-表达式树实现&#xff09;服务优化词频统计&#xff08;树实现&#xff09; 树叶节点遍历&#xff08;树-基础题&#xff09; 【问题描述】 从标准输入中…

OpenCV学习(4.9) OpenCV中的轮廓

1.目标 了解轮廓是什么。学习寻找轮廓&#xff0c;绘制轮廓等您将看到以下功能&#xff1a;**cv.findContours()** &#xff0c;**cv.drawContours()* 2.什么是轮廓 轮廓可以简单地解释为连接具有相同颜色或强度的所有连续点(沿边界)的曲线。轮廓是用于形状分析以及对象检测…

嵌入式学习——Linux高级编程复习(互斥锁、信号量、管道、信号)——day41

1. 同步和异步 1.1 同步 多个任务在某一时刻,先后执行顺序可以被确定 同步操作要求一系列操作严格按照顺序执行&#xff0c;一个操作只有在前一个操作完成之后才能开始。在计算机编程中&#xff0c;这意味着当一个程序或线程发出一个请求或调用后&#xff0c;它会暂停执行&…

java自动化之java基础03-09java基础之数组

数组 1、定义 数组是一种用于存储固定大小的同类型数据的数据结构 1&#xff09;固定大小 2&#xff09;同类型数据的存储 2、声明数组 1&#xff09;数据类型[] 变量名称&#xff1b; 例如&#xff1a;int[] numsArry; 2&#xff09;数据类型 变量名称[]; 例如&#xf…

27.机会成本

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/677 题目描述 明天有 𝑛n 门考试,今晚只…

【C++修行之道】类和对象(五)日期类的实现、const成员、取地址及const和取地址操作符重载

目录 一、 日期类的实现 Date.h 1.1 GetMonthDay函数&#xff08;获取某年某月的天数&#xff09; 问&#xff1a;这个函数为什么不和其他的函数一样放在Date.cpp文件中实现呢&#xff1f; 1.2 CheckDate函数&#xff08;检查日期有效性&#xff09;、Print函数&#xff08;…

计算机毕业设计 | SpringBoot宠物医院管理 宠物商城购物系统(附源码)

写在前面 Le Dao宠物医院管理系统是一个超大型的&#xff0c;完成度很高的&#xff0c;集宠物医疗、宠物美容、宠物交易、宠物周边等各种功能于一身的&#xff0c;权限涵盖普通用户、医生、化验师、美容师、仓库主管、采购员等多种角色于一体的大型宠物医疗&#xff0c;购物系…

Java 数据类型 -- Java 语言的 8 种基本数据类型、字符串与数组

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 004 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

1035 插入与归并(测试点6)

solution 类型判断&#xff1a;插入排序中已排序的部分有序&#xff0c;未排序的和原数组元素相同&#xff1b;否则为归并排序测试点6&#xff1a;对于归并排序的子序列长度&#xff0c;不能简单视为前k个有序则子序列长度就是k 例如该测试用例的归并排序的子序列长度应该为2&…

重新认识Word —— 制作简历

重新认识Word —— 制作简历 PPT的图形减除功能word中的设置调整页边距进行排版表格使用 我们之前把word长排版文本梳理了一遍&#xff0c;其实word还有另外的功能&#xff0c;比如说——制作简历。 在这之前&#xff0c;我们先讲一个小技巧&#xff1a; PPT的图形减除功能 …

记录一次被谷歌封号后又解封的过程

先提前恭祝2024年所有参加高考的学子们都能金榜题名&#xff0c;会的全对&#xff0c;不会的蒙的全对&#xff01; 一、背景 众所周知&#xff0c;谷歌、ios应用市场对app的审查都是极其严格的&#xff0c;开发者稍有不慎就会被谷歌下架应用&#xff0c;乃至封号。我们公司是做…

目标检测应用场景—数据集【NO.36】甘蔗叶片病害识别数据集

写在前面&#xff1a;数据集对应应用场景&#xff0c;不同的应用场景有不同的检测难点以及对应改进方法&#xff0c;本系列整理汇总领域内的数据集&#xff0c;方便大家下载数据集&#xff0c;若无法下载可关注后私信领取。关注免费领取整理好的数据集资料&#xff01;今天分享…

error while loading shared libraries 找不到动态库问题如何解决

在使用 c 或 c 开发应用时&#xff0c;在启动程序时&#xff0c;有时会遇到这个错误&#xff0c;找不到动态库。这个时候&#xff0c;我们使用 ldd 来查看&#xff0c;发现可执行文件依赖的动态库显示为 not found。 1 实验代码 使用如下 3 个文件做实验。 hello.h 中声明了函…

Mysql使用中的性能优化——搭建Mysql的监测服务

大纲 环境安装配置Mysql安装设置root密码新增远程访问账户修改绑定地址重启 新增 MySQL Server Exporter 用户 安装启动mysqld_exporter安装启动新增配置启动直接启动以Service形式启动 安装启动Prometheus创建用户下载并解压修改配置启动 安装启动grafana安装启动 测试参考资料…

地图商家数据怎么查看?揭秘采集软件工作原理!

地图商家数据怎么查看&#xff1f;其实主要就是两种方法&#xff1a; 1. 直接使用地图服务提供的API&#xff1a;大多数地图提供商&#xff08;如Google地图&#xff0c;百度地图等&#xff09;都会提供一些API&#xff0c;通过这些API&#xff0c;可以获取到它们所拥有的商家…

速卖通如何放关联?

大家都知道&#xff0c;想要进行多账号操作必须一再小心&#xff0c;否则会有很大的关联风险&#xff0c;而账号关联所带来的后果是卖家绝对不能轻视的&#xff0c;严重的话会导致封号&#xff0c;这样一来自己前期的辛苦运营就全都打水漂了&#xff0c;因此防关联很重要&#…

vue处理json数据

背景&#xff1a;后端返回的数据不是我想要的&#xff0c;现在需要把 name 替换为title&#xff08;小声蛐蛐&#xff1a;又让我处理数据&#xff09; 后端返回数据格式 修改字段操作&#xff1a;&#xff08;使用递归遍历的方式将title属性赋了name的值&#xff09; renderT…

转让北京劳务分包地基基础施工资质条件和流程

地基基础资质转让流程是怎样的?对于企业来说&#xff0c;资质证书不仅是实力的证明&#xff0c;更是获得工程承包的前提。而在有了资质证书后&#xff0c;企业才可以安心的准备工程投标&#xff0c;进而在工程竣工后获得收益。而对于从事地基基础工程施工的企业&#xff0c;需…

gpt、llama大模型模型结构细节探索

参考&#xff1a; https://github.com/naklecha/llama3-from-scratch&#xff08;一定要看看&#xff09; https://github.com/karpathy/build-nanogpt/blob/master/play.ipynb 视频&#xff1a; https://www.youtube.com/watch?vl8pRSuU81PU https://tiktokenizer.vercel…