【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  31
    
    struct book {          // 结构模板:标记是book
        char 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};
        else
            readfirst = (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定义所在的位置
    

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

保护电脑安全,火绒安全助手 V5.0

火绒安全软件&#xff0c;也称为“火绒安全助手”是一款由中国研发的综合安全软件。火绒安全软件旨在为计算机用户提供全面的安全保护&#xff0c;包括防病毒、反恶意软件、网络安全、系统优化等功能。 火绒安全的功能 病毒防护&#xff1a;火绒提供实时的病毒和恶意软件扫描…

年度征文|回顾2023我的CSDN

一年转眼而逝&#xff0c;回顾这一年在csdn的创作&#xff0c;学习&#xff0c;记录历程。回顾过去&#xff0c;才能展望未来&#xff0c;首先看图说话。 今年在csdn的访问量已由年初的2万到年末的50w。粉丝有年初的300个左右&#xff0c;增加到4000个左右。我年初的目标是粉丝…

nvm安装版本后设置默认镜像地址和nvm list available出现空白解决办法

如题 npm config get registry https://registry.npmjs.org/发现镜像地址依旧是默认的 解决 运行输入npm config list 查看这个选项对应的目录 修改为的内容如下 homehttps://npmmirror.com registryhttps://registry.npmmirror.com/或者也可以 homehttps://npmmirror.com…

【nw.js】使用nw.js将html页面打包成exe免安装程序

文章目录 一、批处理zip命令&#xff08;已有可跳过此步骤&#xff09;二、nw.js包三、使用批处理命令打包成exe可执行文件四、使用EnigmaVB打包成免安装可独立运行的exe文件五、结束 一、批处理zip命令&#xff08;已有可跳过此步骤&#xff09; 下载zip&#xff0c;你可以到该…

【Java并发篇】什么是多线程中的上下文切换?

多线程中的上下文切换 ✔️ 简述✔️拓展知识仓✔️减少上下文切换 ✔️ 简述 上下文切换是指 CPU 从一个线程转到另一个线程时&#xff0c;需要保存当前线程的上下文状态&#xff0c;恢复另一个线程的上下文状态&#xff0c;以便于下一次恢复执行该线程时能够正确地运行。 在…

嵌入式面试准备

题目都摘于网上 嵌入式系统中经常要用到无限循环&#xff0c;如何用C编写死循环 while(1){}或者for(;&#x1f609; 内存分区 代码区&#xff0c;全局区&#xff08;全局变量&#xff0c;静态变量&#xff0c;以及常量&#xff09;&#xff0c;栈区&#xff0c;堆区 const关键…

[SWPUCTF 2021 新生赛]sql

[SWPUCTF 2021 新生赛]sql wp 输入 1 正常回显&#xff1a; ?wllm1 返回&#xff1a; Want Me? Cross the Waf Your Login name:xxx Your Password:yyy输入单引号引发报错&#xff1a; ?wllm1 返回&#xff1a; Want Me? Cross the Waf You have an error in your SQL s…

指点云 宁波大带宽大存储云服务器 性能评测

指点云 浙江宁波 云服务器 性能测评&#xff0c;2核4G 100兆带宽 240G存储 5G防御 仅需76.8元/月&#xff1b;4核8G仅需112.8元/月。 官网地址&#xff1a;https://url.vpszj.cn/zhidianyun 优惠注册地址&#xff1a;https://url.vpszj.cn/zhidianyun_r 性价比高的服务器推荐…

【产品设计】零代码核心模块之三:报表

报表的用于数据和信息呈现的一种方式&#xff0c;能够帮助人们更直观地了解数据和信息&#xff0c;从而做出更明智的决策。本文从报表的价值、产品功能以及数据统计分析出发&#xff0c;探讨报表的重要性与使用场景&#xff0c;希望对你有所启发。 报表适用于需要呈现数据或信息…

Spring高手之路-Spring支持的注入方式、Spring为什么不建议使用基于字段的依赖注入

目录 Spring支持的注入方式 1.字段注入 2.构造器注入 3.setter注入 使用构造器注入存在的问题 Spring为何不建议使用基于字段的依赖注入 1.单一职责问题 2.可能产生NPE&#xff08;空指针异常&#xff09; 3.隐藏依赖 4.不利于测试 Spring支持的注入方式 1.字段注入 A…

k8s的二进制部署: 源码包部署-----node节点部署

服务器IP软件包k8s--master0120.0.0.61kube-aplserver&#xff0c;kube-controer-manager&#xff0c;kube-scheduler&#xff0c;etcdk8s--master0220.0.0.62kube-controer-manager&#xff0c;kube-schedulernode节点0120.0.0.62kubelet&#xff0c;kube-proxy&#xff0c;et…

【http】HTTP/1.0、HTTP/1.1和HTTP/2.0

✨ 专栏介绍 在当今互联网时代&#xff0c;计算机网络已经成为了人们生活和工作中不可或缺的一部分。而要实现计算机之间的通信和数据传输&#xff0c;就需要依靠各种网络协议来进行规范和约束。无论是浏览网页、发送电子邮件还是进行在线交流&#xff0c;都离不开各种各样的网…

2023年航天大事件

2023年&#xff0c;中国完成宇航发射近70次&#xff0c;是中国航天新的里程碑。中国科技工作者继续推进航天科技创新&#xff0c;并在运载火箭发动机研制固体燃料火箭研发、可重复航天器研发等方面取得重大突破&#xff1b;继续推进载人航天工程、北斗工程等中国重大航天旗舰工…

HOJ 项目部署-前端定制 默认勾选显示标签、 在线编辑器主题和字号大小修改、增加一言功能 题目AC后礼花绽放

# 项目拉取地址&#xff1a; https://gitee.com/himitzh0730/hoj.git # 切换到hoj-vue目录执行以下命令 #安装依赖 npm install #运行服务 npm run serve #修改代码后构建项目到dist文件夹&#xff0c;到服务器docker-compose.yml中修改hoj-frontend文件映射即可 npm run build…

python进阶 — Python解释器

1、Python解释器 Python解释器是一个计算机程序&#xff0c;它将Python代码转换为计算机可以理解的机器代码&#xff0c;并执行这些机器代码。 1. 这篇文章介绍如何下载和安装Python解释器&#xff1a; python基础&#xff08;2&#xff09;— 环境搭建 2 . 这篇文章介绍如…

果然,大厂都在卷这个!

大家好&#xff0c;我是鱼皮。首先祝大家平安夜快乐&#xff01;给大家看看我们搞的小圣诞树哈哈&#xff5e; 言归正传&#xff0c;这周中我去北京待了 2 天&#xff0c;主要是收到百度的邀请去参加百度云的智算大会&#xff0c;听说有些 AI 产品要发布。 我自己是非常关注国内…

C#教程(四):多态

1、介绍 1.1 什么是多态 在C#中&#xff0c;多态性&#xff08;Polymorphism&#xff09;是面向对象编程中的一个重要概念&#xff0c;它允许不同类的对象对同一消息做出响应&#xff0c;即同一个方法可以在不同的对象上产生不同的行为。C#中的多态性可以通过以下几种方式实现…

每日一题-----逆序字符串

大家好我是Beilef&#xff0c;在一个美好的下午我意外接触到编程并且产生了兴趣&#xff0c;哈哈我要努力成为一个跨界者&#xff0c;让我们一起加油吧O(∩_∩)O 文章目录 目录 文章目录 前言 大家好请上车 一、逆序字符串 题⽬描述&#xff1a; 输⼊⼀个字符串&#xff0c;写…

UiPath报告 | 2024年7大自动化和Al趋势

在自动化与人工智能的合力推动下&#xff0c;全球企业正在步入一个创造价值的新纪元。 预计市场将涌现出一系列高潜力的AI应用实例&#xff1b; 企业的日常运营和复杂流程管理方式将面临根本性的变革&#xff0c;人工智能的崛起正加速企业自动化进程&#xff0c;促成价值的快速…

【WPF】使用Behavior以及ValidationRule实现表单校验

文章目录 使用ValidationRule实现检测用户输入EmptyValidationRule 非空校验TextBox设置非空校验TextBox设置非空校验并显示校验提示 结语 使用ValidationRule实现检测用户输入 EmptyValidationRule是TextBox内容是否为空校验&#xff0c;TextBox的Binding属性设置ValidationRu…