【C Primer Plus第六版 学习笔记】第十四章 结构和其他数据形式

有基础,进阶用,个人查漏补缺

  1. 建立结构声明:描述该对象由什么组成,即结构布局

    格式:

    关键字 标记(可选){结构
    };
    举例:
    struct book{char title[2];char author[4];float value;
    };
    
  2. 定义结构变量

    结构布局告诉编译器如何表示数据,但是并未让编译器为数据分配空间。创建结构变量,则编译器会使用上述book模板为该变量分配空间。

    struct book library;
    

    在这里插入图片描述

    结构布局和结构变量合并声明

    struct book{char title[2];char author[4];float value;
    }library;//也可以这样,但是就无法多次使用该结构进行其他同结构的变量声明了
    struct{char title[2];char author[4];float value;
    }library;
    
  3. 初始化结构

    与初始化数组的语法类似

    struct book library = {"ab","1234",1.99
    };
    
  4. 访问结构成员

    library.title
    library.author
    library.value
    
  5. 结构的初始化器

    结构的初始化器使用点运算符和成员名标识特定元素

    //只初始化book结构和value成员
    struct book surprise = {.value = 10.99};//可以按照任意顺序使用指定初始化器
    struct book surprise = {.value = 10.99,.author = "ab",.title = "abds"};//此外
    struct book surprise = {.value = 10.99,.author = "ab",25};//赋给value的值是25,取代了10.99
    
  6. 嵌套结构

    #include <stdio.h>
    struct names {              //第一个结构char first[20];char last[20];
    };struct guy{                 //第二个结构struct names handle;char job[20];float age;
    };int main(void)
    {struct guy fellow = {{"Ewen", "Villard"},"coach",25};printf("Dear %s", fellow.handle.first);return 0;
    }
    /*输出:
    Dear Ewen
    
  7. 指向结构的指针

    地址的就使用“→”,标识符的就使用“.”

    #include <stdio.h>
    struct names {              //第一个结构char first[20]; //占用20字节内存char last[20];  //占用20字节内存
    };struct guy{                 //第二个结构struct names handle;char job[20];     //占用20字节内存char favfood[20]; //占用20字节内存float age;        //占用4字节内存
    };int main(void)
    {struct guy fellow[2] = {{{"Ewen", "Villard"},"coach","apple",25},{{"Rob", "Swill"},"editor","banana",30}};struct guy * him;       //声明指向结构的指针
    /*或者有一个guy类型的结构barney,也可以him = &barney*/printf("address #1: %p #2: %p\n", &fellow[0], &fellow[1]);him = &fellow[0];      //告诉编译器该指针指向何处printf("pointer #1: %p #2: %p\n", him, him+1);//两种访问方式printf("him->age is %.f; (*him).age is %.f\n", him->age, (*him).age);**//必须要是用圆括号,因为运算符.比*优先级高!!**him++;printf("him->job is %.s; him->handle.last is %.s\n", him->job, him->handle.last);return 0;
    }
    /*输出:
    address #1: 0x7fff5fbff820 #2: 0x7fff5fbff874  //相差54(十六进制,十进制为84),
    pointer #1: 0x7fff5fbff820 #2: 0x7fff5fbff874  //说明每个guy结构相差84字节内存
    him->age is 25; (*him).age is 25
    him->job is editor; him->handle.last is Swill
    
  8. 向函数传递结构的信息

    #include <stdio.h>
    #define FUNDLEN 50
    struct funds {char   bank[FUNDLEN];double bankfund;char   save[FUNDLEN];double savefund;
    };double sum1(double, double);       /* 1. 传递结构成员 */
    double sum2(const struct funds *); /* 2. 传递结构地址 */
    double sum3(struct funds moolah);  /* 3. 传递结构    */int main(void)
    {struct funds stan = {"Garlic-Melon Bank",4032.27,"Lucky's Savings and Loan",8543.94};/*均输出:Stan has a total of $12576.21.*//* 1. 传递结构成员 */printf("Stan has a total of $%.2f.\n",sum1(stan.bankfund, stan.savefund) );/* 2. 传递结构地址 */printf("Stan has a total of $%.2f.\n", sum2(&stan));/* 3. 传递结构    */printf("Stan has a total of $%.2f.\n", sum3(stan));return 0;
    }
    /* 1. 传递结构成员 */
    double sum1(double x, double y)
    {return(x + y);
    }
    /* 2. 传递结构地址 */
    double sum2(const struct funds * money)
    {return(money->bankfund + money->savefund);
    }
    /* 3. 传递结构    */
    double sum(struct funds moolah)
    {return(moolah.bankfund + moolah.savefund);
    }
    
  9. 结构和结构指针的选择

    1. 结构:
      1. 优点:①函数处理的是原始数据的副本,保护了原始数据;②代码风格更清楚
      2. 缺点:①老版本可能无法实现;②传递结构浪费时间和存储空间
    2. 指针结构:
      1. 优点:①任何C语言版本都可使用;②执行快,只需要传递一个地址
      2. 缺点:无法保护数据,但const解决了这个问题
    3. 通常,为了追求效率会使用指针结构作为函数参数,如果需要防止原始数据被意外修改,使用const限定符。处理小型结构最常用按值传递。
  10. 结构中的字符数组和字符指针

    struct names {char first[20];char last[20];
    };
    struct pnames {char * first;char * last;
    };/*以下三行代码没问题,但veep字符串均储存在结构内部,总共要分配40字节存储姓名,
    而treas的字符串储存在编译器储存常量的地方,结构本身只储存了两个地址,只占用16字节*/
    struct names veep = {"Taila", "Summers"};
    struct pnames treas = {"Brad", "Falling"};
    printf("%s and %s\n", veep.first, treas.first);/*就语法而言,没有问题*/
    /*对于会计师,其名字被储存在accountant结构变量的last成员中,该结构有一个储存字符串的数组*/
    /*对于律师,scanf()把字符串放到attorney.last表示的地址上,
    但这是未经初始化的变量,地址可以是任意值,程序可以把名放在任何地方,可能会导致程序崩溃*/
    struct names accountant;
    struct pnames attorney;
    scanf("%s", accountant.last);
    scanf("%s", attorney.last);
    
  11. 结构、指针、malloc()

    使用malloc()分配内存并使用指针储存该地址,会使得在结构中使用指针处理字符串比较合理。该方法优点是可以请求malloc()为字符串分配合适的存储空间。

  12. 复合字面量和结构(C99)

    C99的复合字面量特性可用于结构和数组

    #include <stdio.h>
    #define MAXTITL  41
    #define MAXAUTL  31struct book {          // 结构模板:标记是bookchar title[MAXTITL];char author[MAXAUTL];float value;
    };int main(void)
    {struct book readfirst;int score;printf("Enter test score: ");scanf("%d",&score);if(score >= 84)readfirst = (struct book) {"Crime and Punishment","Fyodor Dostoyevsky",11.25};elsereadfirst = (struct book) {"Mr. Bouncy's Nice Hat","Fred Winsome",5.99};printf("Your assigned reading:\n");printf("%s by %s: $%.2f\n",readfirst.title,readfirst.author, readfirst.value);return 0;
    }
    
  13. 伸缩型数组成员(C99)

    有两个特性:

    1. 该数组不会立刻存在
    2. 好像它确实存在并具有所需数目的元素一样

    声明伸缩型数组成员的规则:

    1. 伸缩型数组成员必须是结构的最后一个成员
    2. 结构中必须至少有一个成员
    3. 伸缩数组的声明类似普通数组,但其方括号中是空的
    struct flex {int count;double average;double scores[];//伸缩型数组成员
    };
    /*声明一个struct flex类型变量时,不能用scores做任何事,因为没有给这个数组预留存储空间
    C99希望你声明一个指向struct flex类型的指针,然后用malloc()来分配足够的空间,
    以储存struct flex类型结构的常规内容和伸缩型数组成员所需的额外空间
    */
    struct flex * pf;
    pf = malloc(sizeof(struct flex) + 5 * sizeof(double));
    pf->count = 5;
    pf->scores[2] = 18.5;
    
  14. 匿名结构(C11)

    //嵌套结构
    struct names {char first[20];char last[20];
    };
    struct person {int id;struct names name;//嵌套结构成员
    };//在C11中,可以用嵌套的匿名成员结构定义person
    struct person {int id;struct {char first[20];	char last[20];};//匿名结构
    };
    
  15. 联合(union)

    1. 联合(union)是一种数据类型,能在同一个内存空间中储存不同的数据类型(非同时储存)。就是把没有规律、事先不知道顺序的数据类型放在一个结构中

      //该结构可以储存一个int类型,一个double类型和char类型的值
      union hold{int a;double b;char c;
      };union hold A;
      A.a = 1;
      union hold A = B;//可以用另一个联合来初始化,也可以用指定初始化器
      
  16. 枚举类型(enum)

    可以使用枚举类型声明符号名称来表示整型变量。使用enum关键字,创建新“类型”并指定它可具有的值。实际上,enum常量是int类型,因此,只要能使用int类型的地方就可以使用枚举类型。枚举类型的目的是提高程序的可读性。

    //第一个声明创建spectrum作为标记名,允许把enum spectrum作为一个类型名使用
    enum spectrum {red, orange, yellow, green, blue, violet};
    //第二个声明color作为该类型的变量。
    enum spectrum color;
    //第一个声明中花括号内的标识符枚举了spectrum变量可能有的值,
    //因此color可能的值是red、orange、yellow、green、blue、violet,这些red等被称为枚举符
    color = blue;
    if(color == yellow)···;
    for(color = red; color <= violet; color++)···;
    

    虽然枚举符(如red等)是int类型,但是枚举符可以是任意整型变量。此处的spectrum的枚举范围是0~5,所以编译器可以用unsigned char来表示color变量。

    printf("red = %d, orange = %d\n", red, orange);
    /*输出:
    red = 0, orange = 1
    

    默认情况下,枚举列表中的常量都被赋予0、1、2等。

    在switch语句中,可以把枚举常量作为标签。

    赋值:

    enum levels {low = 100, medium = 500, high = 2000};
    enum feline {cat, lynx = 10, ouma, tiger};
    //cat的值为0(默认),lynx,ouma,tiger分别为**10,11,12**
    
  17. typedef

    利用typedef可以为某一类型自定义名称,由编译器解释,不是预处理器

    typedef unsigned char byte;//也可以用大写BYTE,遵循变量的命名规则即可
    byte x, y[10], *z;//该定义的作用域取决于typedef定义所在的位置
    

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

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

相关文章

Redis遇到过的问题 (Could not get a resource from the pool )

生产上通过scan命令&#xff0c;查询一个大key耗时40s后&#xff0c;报 Could not get a resource from the pool&#xff0c;初步报错是连接池的连接数不够&#xff0c;从网上搜了一些解决方案。 排查过程&#xff1a; 一、首先需要先尝试连接redis&#xff0c;如果连接不上那…

Node.js(三)-模块的加载机制

1. 优先从缓存中加载 模块在第一次加载后会被缓存&#xff0c;这就意味着多次调用require()不会导致模块的代码被执行多次。 注意:不论是内置模块、用户自定义模块、还是第三方模块&#xff0c;它们都会优先从缓存中加载&#xff0c;从而提高模块的加载效率. 2. 内置模块的加…

Unity-.meta文件

.meta 文件的作用简单来说是建立 Unity 与资源之间的“桥梁”,可以将meta文件理解不同文件之间的桥梁,通过它引擎可以管理不同文件之间的依赖关系。在游戏中引用一个游戏资源,Unity 并不是直接按照文件的路径或者名称,而是使用一个独一无二的 GUID 来指向工程里该资源文件。…

c++案例汇总

文章目录 结构体案例案例1案例2 结构体案例 案例1 学校正在做毕设项目&#xff0c;每名老师带领5个学生&#xff0c;总共有3名老师&#xff0c;需求如下&#xff1a; 设计学生和老师的结构体&#xff0c;其中在老师的结构体中&#xff0c;有老师姓名和一个存放5名学生的数组作…

欧洲影像学人工智能和影像组 学文章审稿指南解读(一)--本手稿是否专注于AI/影像组学的报告?

欧洲影像学人工智能和影像组 学文章审稿指南解读 针对人工智能&#xff08;AI&#xff09;和影像组学领域的研究文章&#xff0c;欧洲影像学&#xff08;European Radiology&#xff09;期刊为审稿人提出了一系列特别的说明和要求。这些要求不仅仅是审稿的准则&#xff0c;更是…

Git 查询某段时间所有用户提交的代码量并过滤文件格式

获取代码提交用户 git log --format%aN| sort -u | while read name; do echo -en "$name\t"; done;获取代码提交文件的修改情况 git log --authorforwardhuan --prettytformat: --numstat获取代码提交文件的修改情况(过滤文件类型) git log --authorforwardhuan …

gin实现登录逻辑,包含cookie,session

users/login.html {{define "users/login.html"}} <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>登录页面</title> </head> <body><form method"post" a…

使用TLS/SSL Pinning保护安卓应用程序

使用TLS/SSL Pinning保护安卓应用程序 在现代术语中&#xff0c;“SSL”&#xff08;安全套接层&#xff09;通常指的是“TLS”&#xff08;传输层安全&#xff09;。虽然 SSL 和 TLS 不是同一个东西&#xff0c;但 TLS 是 SSL 的改进和更安全的版本&#xff0c;并且在实践中已…

51.网游逆向分析与插件开发-游戏反调试功能的实现-设置主线程为隐藏调试破坏调试通道

前置内容&#xff1a; 50.网游逆向分析与插件开发-游戏反调试功能的实现-TP、NP等反调试驱动的原理-CSDN博客 码云地址&#xff08;master分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;87e45c4acc2e842f147ce0e037731f…

在k8s中将gitlab-runner的运行pod调度到指定节点

本篇和前面的 基于helm的方式在k8s集群中部署gitlab 具有很强的关联性&#xff0c;因此如果有不明白的地方可以查看往期分享&#xff1a; 基于helm的方式在k8s集群中部署gitlab - 部署基于helm的方式在k8s集群中部署gitlab - 备份恢复基于helm的方式在k8s集群中部署gitlab - 升…

Copilot概述:AI助手引领编程新纪元

前言&#xff1a; 随着人工智能&#xff08;AI&#xff09;技术的不断进步&#xff0c;编程领域也在逐渐迎来一场革命。GitHub Copilot&#xff0c;作为一款由 OpenAI 和 GitHub 合作开发的编程助手&#xff0c;引发了广泛的关注和讨论。本篇博客将全面概述 Copilot 的背景、功…

基于gradio快速部署自己的深度学习模型(目标检测、图像分类、语义分割模型)

gradio是一款基于python的算法快速部署工具&#xff0c;本博文主要介绍使用gradio部署目标检测、图像分类、语义分割模型的部署。相比于flask&#xff0c;使用gradio不需要自己构造前端代码&#xff0c;只需要将后端接口写好即可。此外&#xff0c;基于gradio实现的项目&#x…

算法分析的

&#xff08;1&#xff09;一个顾客买了价值x元的商品&#xff08;不考虑角、分&#xff09;&#xff0c;并将y元的钱交给售货员&#xff1a;编写代码&#xff1a;在各种币值的钱都很充分的情况下&#xff0c;使售货员能用张数最少的钱币找给顾客 #include<stdio.h> int…

舒心减压,益路同行,黄埔区惠民社会服务中心开展残障人士冬至漫游活动

“走出家门&#xff0c;共享阳光”残障人士游读广州项目是由广州市慈善会、广州市善城社区公益基金会资助、广州市黄埔区惠民社会服务中心实施的第四届“创善*微创投”广州市社区公益微创投项目&#xff0c;黄埔区康园工疗站约120名残障人士为服务对象&#xff0c;通过游玩与教…

leetcode 371. 两整数之和(优质解法)

链接&#xff1a;371. 两整数之和 代码&#xff1a; class Solution {public int getSum(int a, int b) {while(b!0){int numa^b; //无进位值int bit(a&b)<<1; //进位anum;bbit;}return a;} } 题解&#xff1a; 要计算两个数相加并且不能使用 - 号&#xff0…

【代码混淆】react-native 代码混淆

​ 混淆是指对源代码进行加密、重命名等操作&#xff0c;以增加代码的复杂度&#xff0c;使其难以理解和反编译。 在React Native中&#xff0c;混淆可以通过以下步骤实现&#xff1a; 将JavaScript源代码转换为基于本机平台的二进制代码&#xff0c;可以使用工具如Metro Bun…

【ARM 嵌入式 编译系列 10.4 -- 生成二进制文件】

文章目录 二进制文件生成dd 命令copy文件使用16进制对二进制文件显示 二进制文件生成 在嵌入的工作中&#xff0c;经常会使用到二进制文件&#xff0c;那么我们如何自己生成一个二进制文件呢&#xff1f;接下来介绍如何将一个只包含将32位数据的文件转化为二进制文件&#xff…

人工智能顶会CVPR2022《革新AI预训练:探索KDEP及其在知识蒸馏中的破局之道》论文解读

这里写目录标题 1.引言KDEP的核心概念&#xff1a;与传统知识蒸馏的区别&#xff1a; 2.KDEP方法KDEP的基本设置&#xff1a;KDEP的目标&#xff1a;非参数方法在特征尺寸对齐中的作用非参数对齐的工作原理&#xff1a;**SVD的工作原理**&#xff1a;PTS的基本思想&#xff1a;…

如何在 TypeScript 中遍历 Enum 的两种方案

背景 TypeScript 中有一个 JavaScript 中没有的声明关键字&#xff0c;即 enum ,在 TypeScript 项目开发过程中&#xff0c;我发现使用枚举enum的概率是极高的。枚举是一种特殊的数据类型&#xff0c;它允许开发者定义一个静态变量集合。枚举类型帮助开发者清晰的预设集合中的…

HarmonyOS4.0系统性深入开发04UIAbility组件详解(下)

UIAbility组件间交互&#xff08;设备内&#xff09; UIAbility是系统调度的最小单元。在设备内的功能模块之间跳转时&#xff0c;会涉及到启动特定的UIAbility&#xff0c;该UIAbility可以是应用内的其他UIAbility&#xff0c;也可以是其他应用的UIAbility&#xff08;例如启…