【计算机408学习笔记】C语言(初级) 08结构体与C++引用讲解

08结构体与C++引用讲解

一、上节作业(重点)
  • 假如有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?为便于读者理解题意,这里举例说明如下:假如有3个台阶,那么总计就有3种走法:第一种为每次上1个台阶,上3次;第二种为先上2个台阶,再上1个台阶;第三种为先上1个台阶,再上2个台阶。输入为n,输出为到第n个台阶有几种走法
#include <stdio.h>


int step(int i)
{
    if(i==1 || i==2)
    {
        return i;
    }
    return step(i-1)+step(i-2);
}


int main() {
    int i,res;
    scanf("%d",&i);
    res=step(i);
    printf("%d\n",res);
    return 0;
}
二、结构体-结构体对齐-结构体数组
1.结构体的定义、初始化、结构体数组
  • 有时候需要将不同类型的数据组合为一个整体, 以便于引用, C 语言提供结构体来管理不同类型的数据组合。
  • 声明一个结构体类型的一般形式
struct 结构体名
    {成员表列};
  • 先声明结构体类型, 再定义变量名。
  • 例子
#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"};
    //结构体输出必须单独去访问内部的每个成员
    printf("%d %s %c %d %f %s\n",s.num,s.name,s.sex,s.age,s.score,s.addr);
    scanf("%d%s %c%d%f%s",&s.num,s.name,&s.sex,&s.age,&s.score,s.addr);
    printf("%d %s %c %d %f %s\n",s.num,s.name,s.sex,s.age,s.score,s.addr);
    return 0;
}
  • 结果
1001 lele M 20 85.400002 shenzhen
2002 lili F 22 88 chongqing
2002 lili F 22 88.000000 chongqing
  • 例子
#include <stdio.h>


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

int main() {
    struct student sarr[3];
    int i;
    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;
}
  • 结果
1001 lily M 20 45 shenzhen
1002 bily F 22 78 chongqing
1003 Mary F 23 99 hubei
1001 lily M 20 45.000000 shenzhen
1002 bily F 22 78.000000 chongqing
1003 Mary F 23 99.000000 hubei
  • 结构体类型声明要放在main函数之前,这样main函数中才可以使用这个结构体。工作中往往把结构体声明放在头文件中。
  • 结构体类型声明最后一定要价分好,否则会编译不通。
  • 定义结构体变量时,使用struct 结构体名来定义,否则也会编译不通。
  • 结构体的初始化只能在一开始定义,如果结构体变量已经定义,那么职能对它的每个成员单独赋值。 如果 struct student s={1001,"lele",'M',20,85.4,"Shenzhen"}已经执行, 即 struct student s 已经定义, 就不能再执行 s={1001,"lele",'M',20,85.4,"Shenzhen"}。
  • 采用结构体变量名.成员名形式来访问结构体成员。 例如用 s.num 访问学号。
  • 在进行打印输出时, 必须访问到成员, 而且 printf 中的%类型要与各成员匹配。
  • 使用 scanf 读取标准输入时, 也必须是各成员取地址, 然后进行存储, 不可以写成&s, 即不可以直接对结构体变量取地址。
  • 整型数据(%d) 、 浮点型数据(%f) 、 字符串型数据(%s) 都会忽略空格, 但是字符型数据(%c) 不会忽略空格, 所以如果要读取字符型数据, 那么就要在待读取的字符数据与其他数据之间加入空格。
2.结构体对齐
  • 结构体的大小必须是其最大成员的整数倍。
  • sizeof(s)=68的由来:int num为4字节;char name为20字节;char sex为1字节;int age为4字节;float score为4字节;char addr为30字节;总计63字节;因为结构体的大小必须是其最大成员的整数倍,则char sex处+3字节,char addr处+2字节;总计为68字节。
  • 为什么要进行结构体对齐?为了CPU能够高效读取内存中的数据。
  • 通过地址总线找到数据(每次4个字节),通过数据总线传递数据。
  • 浮点类型分为float(占用4个字节)和double(占用8个字节)。
  • 整型分为short(占用2个字节)和int(占用4个字节)。
  • 例子
#include <stdio.h>


struct student_type1{
    double score;
    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=%d\n",sizeof(s1));
    printf("s2=%d\n",sizeof(s2));
    printf("s3=%d\n",sizeof(s3));
    return 0;
}
  • 结果
s1=16//double占用8字节,int占用4字节,short占用2字节,int+short+补齐的2字节
s2=16//double占用8字节,char占用1字节,short占用2字节,char+short+补齐的5字节
s3=8//int占用4字节,char占用1字节,short占用2字节,char+short+补齐的1字节
  • 如果两个小存储之和是小于最大长度,那么他们就结合在一起。
三、结构体指针与typedef的使用
1.结构体指针
  • 一个结构体变量的指针就是该变量所占据的内存段的起始地址。
  • 可以设置一个指针变量,用它指向一个结构体变量, 此时该指针变量的值是结构体变量的起始地址。 指针变量也可以用来指向结构体数组中的元素, 从而能够通过结构体指针快速访问结构体内的每个成员。
  • 使用(*p).num 访问成员为什么要加括号呢? 原因是“.” 成员选择的优先级高于“*” (即取值) 运算符, 所以必须加括号, 通过*p 得到 sarr[0], 然后获取对应的成员。
  • 结构体指针访问成员,优先使用“→”成员选择。
  • 例子
#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,"zhangshan",'M',1007,"lily",'M'};
    struct student *p;//定义结构体指针


    p=&s;
    printf("%d %s %c\n",(*p).num,(*p).name,(*p).sex);
    printf("%d %s %c\n",p->num,p->name,p->sex);


    p=sarr;//数组名中存储的是数据的首地址,等价于p=&sarr[0];
    printf("%d %s %c\n",(*p).num,(*p).name,(*p).sex);
    printf("%d %s %c\n",p->num,p->name,p->sex);


    p=p+1;
    printf("%d %s %c\n",(*p).num,(*p).name,(*p).sex);
    printf("%d %s %c\n",p->num,p->name,p->sex);
    return 0;
}
  • 结果
1001 wangle M
1001 wangle M
1001 lilei M
1001 lilei M
1005 zhangshan M
1005 zhangshan M
2.typedef的使用
  • 可以选择使用 typedef 声明新的类型名来代替已有的类型名。
  • 使用 stu 定义结构体变量和使用 struct student 定义结构体变量是等价的。
  • pstu 等价于 struct student*, 所以 p 是结构体指针变量。
  • 例子
#include <stdio.h>


//struct student{
//    int num;
//    char name[20];
//    char sex;
//};
//int main() {
//    struct student s={0};
//    return 0;
//}


typedef struct student{
    int num;
    char name[20];
    char sex;
}stu,*pstu;


int main() {
    stu s={0};
    pstu p=&s;//等价于stu *p=&s;
    return 0;
}
  • 使用 INTEGER定义变量 i 和使用 int 定义变量 i 是等价的。
  • 例子
#include <stdio.h>


typedef int INTEGER;//可以修改int类型,后续INTEGER统一修改类型


int main() {

    INTEGER num=10;
    printf("%d\n",num);

    return 0;
}
  • 局部变量名可以与成员名相同。
四、C++引用的讲解
1.C++的引用讲解
  • 对于 C++, 首先新建源文件时, 名字需要叫 main.cpp,以 cpp 后缀结尾。
  • 我们在修改函数外的某一变量时, 使用了引用后, 在子函数内的操作和函数外操作手法一致, 这样编程效率较高, 对于初学者理解也非常方便。
  • 当需要在子函数中修改主函数中变量的值,就用引用,否则,则不用。
  • 例子
main.cpp
#include <stdio.h>
//C++完全兼容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;
}
  • 结果
after modify_num a=11
  • 例子( 上面的代码如果改为纯 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);
}
  • 结果
after modify_num a=11
  • 例子
#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;
}
  • 结果
after modify_pointer *p=10
  • 例子( 上面的代码如果改为纯 C)
#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;
}
  • 结果
after modify_pointer *p=10
2.C++的布尔类型
  • 布尔类型在C语言中没有,在C++中有true和false。
  • 例子
#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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木炭条178

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值