C语言基础(五)——结构体与C++引用

本文详细介绍了C++中结构体的定义、初始化、结构体数组,以及结构体对齐、结构体指针、typedef的运用。还涵盖了C++的引用概念,包括如何在函数内部修改变量值,以及布尔类型的使用提升代码可读性。
摘要由CSDN通过智能技术生成

七、结构体与C++引用

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

C 语言提供结构体来管理不同类型的数据组合。通过将不同类型的数据组合成一个整体,方便引用
例如,一名学生有学号、姓 名、性别、年龄、地址等属性,如果针对学生的学号、姓名、年龄等都单独定义一个变量,那么在有多名学生时,变量就难以分清。就可通过结构体来管理

声明一个结构体类型的一般形式为

struct 结构体名 {成员表列};
struct student 
{ 
    int num;char name[20];char sex; 
    int age;float score;char addr[30]; 
};

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

 struct student student1,student2;

【例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,"lele",'M',20,85.4,"Shenzhen"};
    struct student sarr[3];//定义一个结构体数组变量
    int i;
    //结构体输出必须单独去访问内部的每个成员
    s.num=1003; //单独赋值 输出的值会改变
    printf("%d %s %c %d %f %s\n",s.num,s.name,s.sex,s.age,s.score,s.addr);
    printf("--------------------------------------\n");
//    scanf("%d%s %c%d%f%s",&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,否则也会编译不通。
结构体的初始化只能在一开始定义,如果 struct student s={1001,"lele",'M',20,85.4,"Shenzhen"}已经执行,即 struct student s 已经定义,就不能再执 行 s={1001,"lele",'M',20,85.4,"Shenzhen"}
整型数据(%d)、浮点型数据(%f)、字符串型数据(%s)都会忽略空格,但字符型数据(%c)不会忽略空格,所以读取字符型数据就要在待读取的字符数据与其他数据之间加入空格。

7.2 结构体对齐

结构体本身的对齐规则,考研初试只需要记住,结构体的大小必须是其最大成员的整数倍

结构体对齐,是为了cpu高效的去取内存中上的数据

#include <stdio.h>

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

struct student_type2{
    double score;
    int height;//如果两个小存储之和是小于最大长度8,那么它们就结合在一起
    short age;
};

struct student_type3{
    int height; //4个字节
    char sex;
    short age;
};
//结构体对齐
int main() {
    struct student_type1 s1;
    struct student_type2 s2={1,2,3};
    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;
}

注意:两个小存储挨在一起且和小于最大长度,那两个小存储就结合在一起看 

s1 size=16   //double8 + short 8
s2 size=16   //double>int+short 所以长度为 double8 + (int+short)8
s3 size=8     //int>char+short 所以长度为 int 4 + (char+short)4

7.3 结构体指针与typedef的使用

7.3.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;//定义了一个结构体指针变量
    p=&s;
    //*p要加括号去访问元素是因为.的优先级比*高,如果不加括号就会报错
    printf("%d %s %c\n",(*p).num,(*p).name,(*p).sex);//方式1访问通过指针对象去访问成员
    printf("%d %s %c\n",p->num,p->name,p->sex);//方式2访问通过结构体指针去访问成员,用这种
    p=sarr;
    printf("%d %s %c\n",(*p).num,(*p).name,(*p).sex);//方式1访问通过指针对象去访问成员
    printf("%d %s %c\n",p->num,p->name,p->sex);//方式2访问通过结构体指针去访问成员,用这种
    printf("------------------------------\n");
    p=p+1;
    printf("%d %s %c\n",(*p).num,(*p).name,(*p).sex);//方式1访问通过指针对象去访问成员
    printf("%d %s %c\n",p->num,p->name,p->sex);//方式2访问通过结构体指针去访问成员,用这种
    return 0;
}

1001 wangle M
1001 wangle M
1002 lilei M
1002 lilei M
-------------------------
1003 zhangsan M
1003 zhangsan M

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

7.3.2 结构体的使用

定义结构体变量时使用的语句是 struct student s,这样定义结构体变量有些麻烦,每次都需要写 struct student。可以选择使用 typedef 声明新的类型名来代替已有的类型名

#include <stdio.h>

typedef struct student{
    int num;
    char name[20];
    char sex;
}stu,*pstu; //pstu等价于 struct student*
//typedef的使用,typedef 起别名

typedef int INGETER; //在特定的地方使用 给int起别名
int main() {
    //stu s ={0};//结构体变量初始化为0  stu 等价于struct student
    stu s={1001,"wangle",'M'};
    stu *p=&s;//定义了一个结构体指针
    pstu p1=&s;//定义了一个结构体指针
    INGETER num=10;
    printf("num=%d,p->num=%d\n",num,p->num);
    return 0;
}

7.4 C++的引用

 7.4.1 C++的引用讲解

 对于 C++,建源文件时,名字需要叫 main.cpp,以 cpp 后缀结尾
 使用了引用后,在子函数内的 操作和函数外操作手法一致,这样编程效率较高
【例1.1】在子函数内修改主函数的普通变量的值(C++)

#include <stdio.h>
//C++引用的讲解

//在子函数中要修改主函数中变量的值,就用引用,不需要修改,就不用
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,代码如下:
【例 1.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;
}

【例 1.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;//进程已结束,退出代码为 -1073741819,不为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;
}

7.4.2 C++的布尔类型

布尔类型在 C 语言没有,C++有 true 和 false,值是1和0

【例 2.1】 布尔类型也是有值的

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

a=1,b=0

  • 31
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值