首页 > 其他分享 >12_结构体

12_结构体

时间:2023-08-24 17:34:06浏览次数:51  
标签:12 struct int lucy char stu 结构 name

结构体

结构体: 将多种数据结构封装在一起 形成新的结构

每种数据结构都有自己独立的空间

结构体关键字: struct

结构体类型定义(声明)

image-20230806160756449

#include<stdio.h>
struct stu //定义结构体类型,系统不分配空间
{
    int num; //成员,不支持赋值
    char name[32];
};
int main(int argc, char const *argv[])
{
    struct stu lucy;
    struct stu alix;
    lucy.num = 10; //赋值
    alix.num = 100;
    printf("%d\n", lucy.num);
    printf("%d\n", alix.num);
    return 0;
}

结构体变量初始化

struct stu hq = {"黄齐", 23}; //结构体变量初始化
printf("%s, %d\n", hq.name, hq.age);

使用memset使结构体变量清空

struct stu mark;
memset(&mark, 0, sizeof(mark)); //memset使结构体变量清空

键盘给结构体变量赋值

struct stu ks;
scanf("%d%s", &ks.age, &ks.name);

结构体变量修改值

struct stu kj= {18, "王莹"}; //初始化
kj.age = 18;
//字符串数组 必须使用字符串操作函数进行操作
// kj.name = "王莹"; //error
strcpy(kj.name, "刘渊");
printf("%s, %d\n", kj.name, kj.age);

结构体直接赋值

struct stu xiaoming = {23, "小明"};
struct stu xiaoli = xiaoming;

内存赋值

struct stu xiaoming = {23, "小明"};
struct stu xiaoli;
memcpy(&xiaoli, &xiaoming, sizeof(xiaoming)); //string.h

结构体嵌套

struct Date
{
    int year;
    int month;
    int day;
};

struct student
{
    int num;
    char name[32];
    struct Date date;
};
int main(int argc, char const *argv[])
{
    struct student lucy = {100, "lucy", {2019, 10, 21}};
    printf("%d\n", lucy.date.year);
    return 0;
}

结构体数组

struct stu edu[5] = {{"小明", 20}, {"小丽", 23}, {"小华", 56}, 		{"小齐", 20}, {"小史", 34}};
// memset(edu, 0, sizeof(edu)); //清0
int n = sizeof(edu)/sizeof(edu[0]);
for (int i = 0; i < n; i++)
{
    printf("%s, %d\n", edu[i].name, edu[i].age);
}

结构体指针变量

struct stu lucy = {"lucy", 23};
struct stu *p = &lucy; //指针变量
printf("%s, %d\n", p->name, p->age);
printf("%s, %d\n", (*p).name, (*p).age);
printf("%s, %d\n", (&lucy)->name, (&lucy)->age);

结构体的指针成员

指针成员: 指针变量作为结构体的成员

指针成员指向文字常量区

struct stu
{
    int age;
    char *name; //指针成员
};
int main(int argc, char const *argv[])
{
    struct stu lucy = {18, "lucy"}; //"lucy" ===> 文字常量区
    printf("%c\n", lucy.name[0]); //'l'
    lucy.name[0] = 'U'; //段错误,文字常量区只读
    return 0;
}

指针成员指向堆区

struct stu lucy;
lucy.age = 18;
//让name指向堆区
lucy.name = (char *) calloc(1, 128); 
// lucy.name = "lucy"; //error 内存泄漏 name指向了文字常量区丢失了		堆区空间
strcpy(lucy.name, "lucy");
printf("%s, %d\n", lucy.name, lucy.age); //lucy, 18
lucy.name[0] = 'U';
printf("%s, %d\n", lucy.name, lucy.age); //Uucy, 18
//释放堆区空间
if (lucy.name != NULL)
{
    free(lucy.name);
    lucy.name = NULL;
}

浅拷贝

image-20230810165004028

深拷贝

如果结构体中有指针成员, 尽量使用深拷贝

struct stu bob;
bob.name = (char *) calloc(1, 128);
bob.age = lucy.age;
strcpy(bob.name, lucy.name);

image-20230810165548972

这样就不会出现问题

结构体在堆区 结构体的指针成员指向堆区

struct stu
{
    char *name;
    int age;
};
int main(int argc, char const *argv[])
{
    struct stu *p = NULL;
    p = (struct stu *)calloc(1, sizeof(struct stu));
    p->name = (char *)calloc(1, 128);
    p->age = 32;
    strcpy(p->name, "lucy");
    printf("%s, %d\n", p->name, p->age);
    if (p->name != NULL) //先释放成员变量
    {
        free(p->name);
        p->name = NULL;
    }
    if (p != NULL) //后释放结构体指针
    {
        free(p);
        p = NULL;
    }
    return 0;
}

结构指针数组

image-20230811223612502

struct stu
{
    char *name;
    int age;
};

int main(int argc, char const *argv[])
{
    struct stu **arr = NULL;
    int n = 5; // 结构数组元素个数
    arr = (struct stu **)calloc(n, sizeof(struct stu *));
    for (int i = 0; i < n; i++)
    {
        arr[i] = (struct stu *)calloc(1, sizeof(struct stu));
        arr[i]->age = 10 + i;
        arr[i]->name = (char *)calloc(1, 128);
        sprintf(arr[i]->name, "lucy%d", i);
    }
    for (int i = 0; i < n; i++)
    {
        printf("%s, %d\n", arr[i]->name, arr[i]->age);
    }
    for (int i = 0; i < n; i++)
    {
        if (arr[i]->name != NULL)
        {
            free(arr[i]->name);
            arr[i]->name = NULL;
        }
        if (arr[i] != NULL)
        {
            free(arr[i]);
            arr[i] = NULL;
        }
    }
    if (arr != NULL)
    {
        free(arr);
        arr = NULL;
    }

    return 0;
}

结构体自动类型对齐

对齐规则

image-20230817143329276

确定分配单位(一行分配多少字节)

结构体中最大的基本类型长度决定(char 1 int 4 short 2 long 8)

确定成员的偏移量

成员偏移量 = 成员自身类型的整数倍

struct Data
{
  char a; //1字节
  int b; //4字节
  short c; //2字节
}

image-20230817152033848

收尾工作

结构体的总大小 = 分配单位的整数倍

结构体嵌套结构体 自动对齐规则

确定分配单位(一行分配多少字节)

所有结构体中最大的基本类型长度决定(char 1 int 4 short 2 long 8)

确定成员的偏移量

普通成员偏移量 = 成员自身类型的整数倍

结构体成员的偏移量 = 该结构体中最大的基本类型的 整数倍

收尾工作

结构体的总大小 = 分配单位的整数倍

例子:

image-20230817180213288

image-20230817180500035

强制对齐

#pragma pack(value) 

image-20230818144653200

结构体的位域

位域(位段): 结构体中以位为单位的成员

struct Data
{
  unsigned int a: 2; //a类型是unsigned int 大小只占2位二进制位
}

image-20230818154922962

不要对位域取地址:

struct A Adata;
&Adata.a; //错误, 系统以字节为单位分配地址空间, 这里是位

对位域赋值 不用超过 位域本身位的宽度

data.a = 5; //溢出

另起一个存储单元

unsigned char : 0; //另起一个存储单元

image-20230818160651173

无意义位段

struct Data
{
    unsigned char a: 4;
    unsigned char : 2; //两位无意义位段
    unsigned char b: 2;
}data;
printf("%lu\n", sizeof(data)); //1字节

image-20230818160955980

共用体 union

结构体: 所有成员拥有独立空间

共用体: 所有成员共享一块空间

union Data
{
  char a;
  short b;
  int c;
};

成员abc共享同一块空间(最大成员空间决定)

union Data data;
data.a = 10;
data.b = 20;
data.c = 30;
printf("%d\n", data.a + data.b + data.c); //90(30+30+30)

成员共享同一块空间,但每个成员能操作的空间由成员自身类型长度决定

image-20230824165754541

image-20230824170136361

共用体将众多结构体统一, 但每个共用体空间只能存放一个数据,否则会覆盖

image-20230824171333862

枚举 enum

枚举: 将枚举变量要赋的值一一列举出来

int poker_color;
enum POKER_COLOR{HONGTAO, MEIHUA, FANGKUAI, HEITAO}; //枚举列表的值默认从0开始递增

image-20230824172217860

image-20230824172350862

标签:12,struct,int,lucy,char,stu,结构,name
From: https://www.cnblogs.com/mzx233/p/17654708.html

相关文章

  • Python数据结构:哈希表
    哈希散列(哈希)是电脑科学中一种对资料的处理方法,通过某种特定的函数/算法(称为散列函数/算法)将要检索的项与用来检索的索引(称为散列,或者散列值)关联起来,生成一种便于搜索的数据结构(称为散列表)。哈希表是什么哈希表(散列表)是根据键(Key)直接访问内存存储位置的数据结构。根据键(Key)值......
  • JavaSE(2)(简单了解idea, 项目结构,运算符,数据转换,原反补码)
    JavaSE(2)(简单了解idea,项目结构,运算符,数据转换,原反补码)p28idea项目结构project项目 > module模块 > package包 > class类拿微信举例,微信就是项目,它下方的四大功能(微信,通讯录,发现,我)就是模块,一个项目是包含一个或多个模块的.以第一个微信模块为例,我们......
  • 5.14 汇编语言:仿写Switch选择结构
    选择结构,也称为switch语句,是计算机编程中的一种控制结构,用于根据表达式的值选择不同的执行路径。它允许程序根据表达式的值来决定执行哪个代码块,从而实现多分支选择逻辑。switch语句由一个表达式、多个case标签以及对应的代码块组成。程序会将表达式的值与每个case标签进行匹配,一......
  • windows 桌面GUI自动化- 12.pywinauto 组合框控件ComboBox操作
    前言pywinauto组合框控件ComboBox操作场景记事本-另存为-编码选择,下图这种就是组合框控件ComboBoxselect选择官网给的教程是通过select选择选项示例frompywinautoimportApplicationapp=Application('uia').start("notepad.exe")win=app.window(title_re="......
  • 学习JAVA的第一天:熟悉IDEA结构并新建工程、模块、包、类。
    新建工程、模块、包、类创建模块:新建package包:包的命名也有要求,一般使用公司域名的倒写,如果公司域名是:www.baidu.com,那么包的命名则是:com.baidu.XXXXXX新建类:IDEA快捷输入mainsout编译总结IDEA的结构分为:项目project-模块module-包package-类class。项目proj......
  • 4目录结构信息
    目录挂载初识定义挂载设备信息 1. 光驱设备---/cd/cdrom 2.完成设备挂载操作 进行挂载---mount/dev/cdrom/mnt/ 3.检查测试挂载结果 挂载检查---df-h 4.挂载完成进行卸载 完成卸载---umount/mnt网卡配置文件 文件信息: /etc/syscon......
  • 【SDE】Centos7 离线安装 Postgresql 12 并配置 sde
    使用ArcGIS10.9.1对应的Postgresql12.7rpm包postgresql12-12.7-1PGDG.rhel7.x86_64.rpmpostgresql12-contrib-12.7-1PGDG.rhel7.x86_64.rpmpostgresql12-libs-12.7-1PGDG.rhel7.x86_64.rpmpostgresql12-server-12.7-1PGDG.rhel7.x86_64.rpmlibicu-50.2-4.el7_7.x......
  • 5.10 汇编语言:汇编过程与结构
    过程的实现离不开堆栈的应用,堆栈是一种后进先出(LIFO)的数据结构,最后压入栈的值总是最先被弹出,而新数值在执行压栈时总是被压入到栈的最顶端,栈主要功能是暂时存放数据和地址,通常用来保护断点和现场。栈是由CPU管理的线性内存数组,它使用两个寄存器(SS和ESP)来保存栈的状态,SS寄存......
  • 5.12 汇编语言:仿写While循环语句
    循环语句(While)一种基本控制结构,它允许程序在条件为真的情况下重复执行一段代码块,直到条件为假为止。循环语句在处理需要重复执行的任务时非常有用,它可以让程序更加高效地处理大量数据或者重复性操作。一般来说,While循环由一个条件表达式、一个代码块组成。在每次循环迭代开始时,程......
  • 2磁盘结构与管理
    磁盘的几个概念:磁盘、磁面、磁道、扇区、柱面一个磁面有多个磁道一个扇区包含多个磁道每个盘面都有读写磁头存取时间=寻道时间+等待时间读取磁盘数据的时间包括三个部分:1、找磁道时间2、找块扇区的时间,即旋转延迟时间3、传输时间磁盘移臂调度算法先来先服务:FCFS(谁先申......