【C语言】C语言期末突击/考研--结构体与C++引用

news2024/10/1 21:35:14

一、结构体--结构体对齐--结构体数组

1.1.结构体的定义、初始化、结构体数组

    有时候需要将不同类型的数据组合为一一个整体,以便于引用。 例如,一名学生有学号、姓
名、性别、年龄、地址等属性,如果针对学生的学号、姓名、年龄等都单独定义一个变量,那么在有多名学生时,变量就难以分清。为此,C语言提供结构体来管理不同类型的数据组合。
声明一个结构体类型的一般形式为:

struct        结构体名
                {成员表列};

例如,

struct  student
        {
                int num;char name[20];char sex;
                int age;float score;char addr[30];
        };

先声明结构体类型,再定义变量名。例如:

struct student        student1, student2;

接下来看例1.1。

【例1.1】 结构体的scanf读取和输出。

#include <stdio.h>
struct student{
    int num;
    char name[20];
    char sex;
    int age;
    float score;
    char addr[30];
}; //结构体类型声明,注意最后一定要加分号

int main() {
    struct student s = {1001, "mumu", 'M', 20, 85.4, "Shenzhen"}; //定义及初始化
    struct student sarr[3];
    int i;
    printf("%d %s %c %d %f %s \n", s.num, s.name, s.sex, s.age, s.score, s.addr);
    for (i = 0; i < 3; i++) {
        scanf("%d%s %c%d%f%s", &sarr[i].num, sarr[i].name, &sarr[i].sex,
              &sarr[i].age, &sarr[i].score, sarr[i].addr);
    }
    for (i = 0; i < 3; i++) {
        printf("%d %s %c %d %f %s\n", sarr[i].num, sarr[i].name, sarr[i].sex,
               sarr[i].age, sarr[i].score, sarr[i].addr);
    }
    return 0;
}

    结构体类型声明要放在main函数之前,这样main函数中才可以使用这个结构体,工作中往往把结构体声明放在头文件中。注意,结构体类型声明最后一定要加分号,否则会编译不通。另外,定义结构体变量时,使用struct student来定义,不能只有struct或student,否则也会编译不通,sarr 是结构体数组变量。结构体的初始化只能在一开始定义,如果struct students={1001,"lele",'M' ,20,85.4,"Shenzhen"}已经执行,即struct student s已经定义,就不能再执行s=1001,"lele'",'M',20,85.4,"Shenzhen"}.如果结构体变量已经定义,那么只能对它的每个成员单独赋值,如s.num=1003.

    采用“结构体变量名.成员名”的形式来访问结构体成员,例如用s.num访问学号。在进行打印输出时,必须访问到成员,而且printf中的%类型要与各成员匹配。使用scanf读取标准输人时,也必须是各成员取地址,然后进行存储,不可以写成&s,即不可以直接对结构体变量取地址。整型数据(%d) 、浮点型数据(%f) 、字符串型数据(%S) 都会忽略空格,但是字符型数据(%c) 不会忽略空格,所以如果要读取字符型数据,那么就要在待读取的字符数据与其他数据之间加人空格。例1.1中代码的运行结果如图1.1所示,我们可以将运行结果保存到文本文档中。例如,每次运行程序时,在窗口中直接粘贴(通过ctrl v来粘贴),进而方便多次测试。 

 

1.2.结构体对齐

    结构体本身的对齐规则有好几条,比较难记,而且对于考研初试完全没有必要,考研初试只需要记住一条,结构体的大小必须是其最大成员的整数倍!下面我们我们来通过例子来实战。
【例】结构体对齐

#include <stdio.h>

struct student_type1{
    double score;//double是一种浮点类型, 8个字节浮点分为float和double,记住有这两种即可
    short age;
};

struct student_type2{
        double score;
        int height;
        short age;
};

struct student_type3{
    int height;
    char sex;
    short age;
};
int main(){
    struct student_type1 s1;
    struct student_type2 s2;
    struct student_type3 s3;
    printf("s1 size=%d\n",sizeof(s1));
    printf("s2 size=%d\n",sizeof(s2));
    printf("s3 size=%d\n",sizeof(s3));
    return 0;
}

上面的例子运行效果如下:

二、结构体指针与typedef的使用

2.1.结构体指针

    一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设置一个指针变量,用它指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素,从而能够通过结构体指针快速访问结构体内的每个成员。下面来看例1.1。
【例2.1】结构体指针的使用:

#include <stdio.h>
//结构体指针
struct student{
    int num;
    char name[20];
    char sex;
};
int main() {
    struct student s = {1001, "wangle", 'M'};
    struct student sarr[3] = {1001, "lilei", 'M', 1005, "zhangsan", 'M', 1007, "lili",'f'};
    struct student *p; //定义结构体指针
    int num;
    p=&s;
    printf("%d %s %c\n", p->num, p->name, p->sex);
    p=sarr;
    printf("%d %s %c\n", (*p).num, (*p).name, (*p).sex); //方式一获取成员
    printf("%d %s %c\n", p->num, p->name, p->sex); //方式 二获取成员
    printf("------------------------\n");
    p=p+1;
    printf("%d %s %c\n", p->num, p->name, p->sex);
    return 0;
    }


    由例2.1可以看到,p就是一个结构体指针,可以对结构体s取地址并赋给p,这样借助成员选择操作符,就可以通过p访问结构体的每个成员,然后进行打印。我们知道数组名中存储的是数据的首地址,所以可以将sarr赋给p,这样就可以通过两种方式访问对应的成员。使用(*p).num访问成员为什么要加括号呢?原因是“.” 成员选择的优先级高于“*”(即取值)运算符,所以必须加括号,通过*p得到sarr[0],然后获取对应的成员。 

 

2.2.typedef的使用

    前面定义结构体变量时使用的语句是struct students,以这种方式来定义结构体变量有些麻烦,即每次都需要写struct student。那么有没有简单一些的定义方式呢?答案是肯定的,可以选择使用typedef声明新的类型名来代替已有的类型名,请看例2.1。
【例2.2】 typedef 的使用:

#include <stdio.h>
//结构体指针
typedef struct student{
    int num;
    char name[20];
    char sex;
}stu,*pstu;

typedef int INTEGER;

int main(){
    stu s={1001,"wangle",'M'};
    pstu p;
    INTEGER i=10;
    p=&s;
    printf("i=%d,p->num=%d\n",i,p->num);
    return 0;
}

    使用stu定义结构体变量和使用structstudent定义结构体变量是等价的;使用INTEGER定义变量i和使用int定义变量i是等价的; pstu 等价于struct student*,所以p是结构体指针变量。

三、C++引用

3.1.C++的引用细则

    对于C++,首先新建源文件时,名字需要叫main.cpp,以cpp后缀结尾,不能像我们之前那样叫main.c。使用C++的引用呢,原因是很多数据结构都采用了这个做法,下面我们来看一下引用的便捷性。

int a; 
void modifynum(int &b)
{
        b=b+1;
}
调用: modifynum(a)


int *p=NULL;
void modify_ pointer(int *&p)
{
        p==q;
}
调用: modify_ pointer(p)

    如上面两个例子所示,我们在修改函数外的某一变量时, 使用了引用后,在子函数内的操作和函数外操作手法一致,这样编程效率较高,对于初学者理解也非常方便。那这种C++的写法,和C语言的代码又是如何对应的呢?下面我们来看一下代码对应关系。
【例3.1】在子函数内修改主函数的普通变量(是C++代码,新建项目要建为C++项目)

#include <stdio.h>

void modify_num(int &b)
{
    b = b + 1;
}
int main() {
    int a=10;
    modify_ num(a);
    printf("after modify_ .num a= =%d\n",a);
    return 0;
}

上面的代码如果改为纯C,代码如下:
【例3.2】 在子函数内修改主函数的普通变量(纯C代码) 

#include <stdio.h>
void modify_num(int *b) {
    *b = *b + 1;
}

int main() {
    int a = 10;
    modify_num(&a);
    printf("after modify_num a=%d\n", a);
    return 0;
}

 【例3.3】子函数内修改主函数的一级指针变量(这是是重要的!)

#include <stdio.h>
void modify_pointer(int* &p,int *q)
{
    p=q;
}
int main() {
    int *p = NULL;
    int i = 10;
    int *q = &i;
    modify_pointer(p, q);
    printf("after modify_ pointer *p=%d\n", *p);
    return 0;
}

上面的代码如果改为纯C,就需要使用到二级指针。二级指针我们没有讲解,因为对于考研初试是使用不到的,因此下面的代码不明白完全没关系,代码如下:

#include <stdio.h>
void modify_pointer(int **p,int *q)
{//相对于C++这里是int **p;
    *p=q;//这里的写法和例1.2中的是非常类似的
}
int main() {
    int *p=NULL;
    int i=10;
    int *q=&i;
    modify_pointer(&p,q);//相对于C++这里是&p
    printf("after modify_ pointer *p= :%d\n",*p);
    return 0;
}

 

3.2.C++的布尔类型

    布尔类型在C语言没有,是C++的,有true和false,通过下面代码我们来理解一下它们:
【例3.4】 布尔类型也是有值的

#include <stdio.h>
//设置布尔值的好处是提升J代码的可阅读性
int main() {
    bool a=true;
    bool b= false;
    printf("a=%d,b=%d\n", a,b);
    return 0;
}

四、练习题及解析 

4.1.结构体--结构体对齐--结构体数组

4.2.结构体指针与typedef的使用

4.3.C++引用

 

致最后

    文章写到这里,本专栏的内容就告一段落啦,希望C语言能够带给您编程的快乐。天色将晚,余晖仍在,就在这样的时刻,我画上了本栏目的最后一个句点。 我推开窗,微风拂面,树影婆娑,恰如此刻我的心境平静而喜悦。今天和往常并没有什么不同,只是内心增添了一分不舍,不论对自己还是对未来都越发充满信心。这种信心来自于一直以来对美好生活的向往与追寻,更来自于在这段生命历程中所感受到的温暖与关爱。这将近十天来对C语言探索与磨练,在此时此地可以收获这样一份满足。最后感谢各位读者的阅读和支持,这些点滴感动我都会铭记于心。我依然会背上思想的行囊继续旅行,带上所有的感激和祝福。

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

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

相关文章

代码坏味道有24种?我看未必

微信公众号&#xff1a;牛奶 Yoka 的小屋 有任何问题。欢迎来撩~ 最近更新&#xff1a;2024/08/03 [大家好&#xff0c;我是牛奶。] 我在上一篇文章打开IDEA&#xff0c;程序员思考的永远只有两件事&#xff01;中&#xff0c;通过代码命名、重复代码、合格方法三个章节&#…

PXE实验

实验前准备 关闭VMware的dhcp 点击 编辑 点击 虚拟网络编辑器 选择 NAT模式 将dhcp取消勾选 准备两台虚拟机 一台试验机&#xff0c;&#xff08;网络环境正常并且有图形化的界面的rhel7&#xff09; 一台测试机 init 5 --------------> 开启图形化界面 如…

《C/C++实战进阶》介绍

&#x1f680; 前言 本文是《C/C实战进阶》专栏的说明贴&#xff08;点击链接&#xff0c;跳转到专栏主页&#xff0c;欢迎订阅&#xff0c;持续更新…&#xff09;。 专栏介绍&#xff1a;以多年的开发实战为基础&#xff0c;总结并讲解一些的C/C基础与项目实战进阶内容&…

AI用Alice_split_toolset切割音频的采样率

AI用Alice_split_toolset切割音频的采样率 目录 AI用Alice_split_toolset切割音频的采样率 一、Sample rate采样率的概念 二、Alice_split_toolset切割音频的参数 2.1、字符串参数--input_folder输入文件夹路径 2.2、字符串参数--output_folder输出文件夹路径 2.3、字符串…

第一次作业,sql注入总结

sqli-labs靶场中演示&#xff1a; less1&#xff1a; 注入点为&#xff1a; $sql"SELECT * FROM users WHERE id$id LIMIT 0,1"; get输入一个id&#xff0c;可以逃逸出单引号来实现sql注入。 正常的输入为&#xff0c;输出数据库中查询的内容。 http://127.0.0…

如何将PyCharm 中使用 PDM 管理的 Django 项目迁移到 VS Code 并确保一切正常工作?

嗨&#xff0c;我是兰若姐姐&#xff0c;相信很多小伙伴都遇到过这种情况&#xff0c;使用pycharm用习惯了&#xff0c;想换个编辑器&#xff0c;比如换成vscode&#xff0c;今天就告诉大家&#xff0c;如果轻松切换到vscode 步骤 1&#xff1a;在 VS Code 中打开项目 打开 V…

并行状态的广播事件

平行状态的广播事件 此示例显示了并行状态下事件广播操作的行为。 最初&#xff0c;图表处于休眠状态。并行子状态A.A1.A1a和A.A2.A2a处于活动状态。事件E_one发生并唤醒图表&#xff0c;图表从根向下通过层次结构处理事件&#xff1a; 1 图表根会检查根级别是否存在E_one导致…

Docker简介 MacM1安装Docker

文章目录 1 Docker简介2 Docker VS 虚拟机1 Docker优势2 Docker用途 3 MacM1 下载安装Docker1 配置环境变量 4 配置Docker2 设置Docker资源3 设置Docker镜像 参考 1 Docker简介 Docker主要解决了软件开发和运行配置的问题&#xff0c;但是由于其功能的强大&#xff0c;也被应用…

跨境电商下载工具天猫主图sku图等图片信息

优美的图片是电商卖家吸引顾客、展示商品魅力的关键。高质量的图片能够提升产品吸引力&#xff0c;增强用户信任感&#xff0c;促进购买决策&#xff0c;从而直接影响销量和店铺形象。在视觉营销的时代&#xff0c;优秀的商品图片更是流量转化的利器。 使用图快下载器&#xf…

多租户系统数据隔离方案

目录 前言 数据行 数据表 基于业务场景 基于数据量 数据库 数据源表 动态数据源 前言 多租户系统是一种将多个客户的数据和应用程序分开的系统&#xff0c;每个客户被视为一个独立的租户&#xff0c;互不干扰。实现多租户系统的关键之一是确保数据的隔离。 数据隔离的…

Windows 添加自定义服务实现开机(用户登录之前)自动运行 Python 脚本

实现效果 使用 Python 编写的一个脚本, 希望在 Windows 系统启动时, 用户登录之前就自动运行. 准备工作 首先确保 Python 脚本可以手动正常运行, 演示起见, 编写下面的一个简单的脚本用于在 C 盘根目录中生成一个包含脚本运行时间戳的文本文件. Python 脚本存放在 C:\Python…

RISC-V (五)上下文切换和协作式多任务

任务&#xff08;task&#xff09; 所谓的任务就是寄存器的当前值。 -smp后面的数字指的是hart的个数&#xff0c;qemu模拟器最大可以有8个核&#xff0c;此文围绕一个核来讲。 QEMU qemu-system-riscv32 QFLAG -nographic -smp 1 -machine virt -bios none 协作式多任务 …

绘唐科技,绘唐3高级推理创作

绘唐科技&#xff0c;绘唐3高级推理创作绘唐3https://qvfbz6lhqnd.feishu.cn/wiki/D3YLwmIzmivZ7BkDij6coVcbn7W 《绘唐3&#xff1a;高级推理创作》 第一章&#xff1a;谋杀案的启示 在古代绘唐王朝的京都&#xff0c;发生了一起离奇的谋杀案。一位名叫李红的官员&#xff0c…

[Day 44] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

生成对抗网络&#xff08;Generative Adversarial Networks&#xff0c;GANs&#xff09;是一种由Ian Goodfellow等人在2014年提出的深度学习模型&#xff0c;广泛用于图像生成、图像超分辨率、图像修复等领域。GAN由一个生成器&#xff08;Generator&#xff09;和一个判别器&…

状态同步帧同步

帧同步&#xff1a; 有明确的逻辑帧概念&#xff0c;按照固定的逻辑帧间隔同步帧数据 原理 锁帧&#xff1a;mmo那种游戏&#xff0c;服务器需要收到第k帧所有客户端的指令&#xff0c;就算没有操作也发个空指令上去&#xff08;相对来说回合制卡牌这类就简单很多&#xff0…

keil编程时,出现”MULTIPLE PUBLIC DEFINITIONS“,extern声明时不能赋值

原因导致重复定义&#xff1f; 有可能是重复定义导致的&#xff0c;这就需要查看报错位置的变量或函数是不是被重复定义了。也可能是一些语法错误导致的错误 语法错误导致的错误原因 使用extern只是为了说明这个变量在别的地方已经定义过&#xff0c;但使用extern引用时&…

NSS [HNCTF 2022 WEEK3]ssssti

NSS [HNCTF 2022 WEEK3]ssssti SSTI类题目&#xff08;flask&#xff09;毋庸置疑。 有过滤&#xff0c;我们拿burp先fuzz一波。长度159的都是被过滤的。 过滤了下划线、引号、args、os。 我们利用request对象绕过对下划线和引号的过滤&#xff08;题目不允许POST方法&#x…

【机器学习】过拟合和欠拟合、高偏差(High Bias)和高方差(High Variance)的区别、过拟合和欠拟合的示例以及图表表示

引言 在机器学习中&#xff0c;过拟合&#xff08;Overfitting&#xff09;是指模型在训练数据上学习得太好&#xff0c;以至于它捕捉到了数据中的噪声和随机波动&#xff0c;而不是潜在的真实关系&#xff0c;这导致模型在新的、未见过的数据上表现不佳&#xff1b;欠拟合&…

从零开始:MySQL安装与配置完全指南

前言 哇&#xff0c;终于进入到令人激动的MySQL环节了 它可以说是你编程生涯中的最佳朋友&#xff0c;因为它总是能存储你的数据&#xff0c;从不说&#xff1a;“我忘记了你的信 息”。而且&#xff0c;它是免费的&#xff0c;不像一些昂贵的数据库&#xff0c;它从不让你的…

部署k8s+conatinerd环境

1、准备系统环境 禁用默认休眠&#xff08;可选&#xff09; 禁用&#xff1a;systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target启用&#xff1a;sudo systemctl unmask sleep.target suspend.target hibernate.target hybrid-sleep.target …