考研C语言第八章

本文介绍了C语言中结构体的定义、初始化以及结构体数组的使用。示例代码展示了如何读取和存储结构体数据,以及结构体对齐的重要性,确保CPU高效读取内存。此外,还讨论了结构体指针的使用,typedef简化类型定义,并提到了C++中的引用概念。
摘要由CSDN通过智能技术生成

结构体定义,初始化,结构体数组

结构体对齐

在这里插入图片描述
这个东西看着像数据库里面属性的定义,也像java里面的类的定义

#include <stdio.h>
#include <string.h>
#include <stdlib.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;
}

关于结构体里面scanf读取输入的数据,并进行相关的存储,
这里面字符串就像之前的,取数据时可以和前面的不加空格,可以不加取地址符号
(但是为了好记和规范,建议直接所有的一视同仁)
在这里插入图片描述
就想数据库在输入数据的时候也每一列数据都需要读入,不然容易写入异常或者失败,一个意思
在这里插入图片描述
结构体数组练习:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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

int main()
{
    struct student arr[3];
    for(int i=0;i<3;i++)
    {
        scanf("%d %s %c %d %f %s",&arr[i].num,&arr[i].name,&arr[i].sex,&arr[i].age,&arr[i].score,&arr[i].addr);
    }
    for(int j=0;j<3;j++)
    {
        printf("%d %s %c %d %f %s\n",arr[j].num,arr[j].name,arr[j].sex,arr[j].age,arr[j].score,arr[j].addr);
    }
//    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;
}

在这里插入图片描述
计算结构体对齐:(例题很复杂)
在这里插入图片描述
在这个例题里面结构是:
63+3+2
其中63是:int是4个字节,char数组20个,char一个,int 四个float四个,char30三十个
4+20+1+4+4+30=63个
在这里我们的结构体是相对于int char float这些类型,不是针对于数组的(也就是本题的20,30)
本来63是针对于一个字节整除,现在最大成员是4(int 和float的)从一个变成四个需要加三
63+3
然后前五个属性没有问题了,看最后一个char30
30不能整除4,需要变成32才能整除4
所以需要+2
63+3+2=68
在这里插入图片描述
为什么要结构体对齐?CPU高效的去读取内存上的数据
详见机组
上面的图,本来一次只能读四个字节,但是先放了1个字节的数据之后,又放了20个字节的数据,就把20个字节拆开了,本来读取五次就可以完全读取完毕,但是现在最后还余一个,不完整

下面还有几个例题:
在这里插入图片描述
double是8个,short是2个
8+2=10,但是还要按照8进行对齐
16
在这里插入图片描述
double 8 int 4 short 2
8+4+2=14还是按照8
16
(ps:老师说4个字节和2个字节是可以堆在一起的,就可以只看8)
在这里插入图片描述
int 4 char 1 short 2 4+1+2=7
按照四个字节凑,8

结构体指针,typedef

在这里插入图片描述

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct student{
    int num;
    char name[20];
    char sex;
};

int main()
{
    struct student s={1001,"wangle","M"};
    struct student arr[3]={1001,"lilei","M",1005,"zhangsan","M",1007,"lili","F"};
    struct student *p;
    p=&s;
    printf("%d %s %c\n",(*p).num,(*p).name,(*p).sex);
    return 0;
}

(*p).num这么写的原因是.的优先级比**的优先级高,所以需要加个括号
但是很显然这个不方便

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

用这一种,箭头的比较方便

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct student{
    int num;
    char name[20];
    char sex;
};

int main()
{
    struct student s={1001,"wangle",'M'};
    struct student arr[3]={1001,"lilei",'M',1005,"zhangsan",'M',1007,"lili",'F'};
    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=arr;
    //上面这个等价于p=&arr[0];
    return 0;
}

上面有一些没改!!sex的地方必须是单引号,字符串的地方是双引号(严格!)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct student{
    int num;
    char name[20];
    char sex;
};

int main()
{
    struct student s={1001,"wangle",'M'};
    struct student arr[3]={1001,"lilei",'M',1005,"zhangsan",'M',1007,"lili",'F'};
    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=arr;
    p=p+1;
    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);
    p=p+1;
    printf("%d %s %c\n",p->num,p->name,p->sex);
    //上面这个等价于p=&arr[0];
    return 0;
}

每次p+1都是偏移一整个结构体的偏移量,也就是正好是一个学生的全部属性数据

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

int main()
{
    stu s={0};
    stu *p=&s;//定义了一个结构体指针变量
    pstu p1=&s;//定义了一个结构体指针变量
    return 0;
}

typedef起别名的操作,缩减了代码量

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

int main()
{
    stu s={1001,"zhangsan",'M'};
    stu *p=&s;//定义了一个结构体指针变量
    pstu p1=&s;//定义了一个结构体指针变量
    INGETER num=10;
    printf("%d %s %c\n",p->num,p->name,p->sex);
    printf("num=%d\n",num);
    return 0;
}

这里面假如还定义了属性,恰好和结构体里面某个属性重名,就可以用typedef进行替换,这里面是将int替换成了INGETER,这样在输出的时候也不会出错:
在这里插入图片描述
8.4开始使用了C++的引用
C++的语法里面新加入的传参数的话需要加取地址符
在这里插入图片描述

#include <stdio.h>

void modify_num(int &b)
{
    b=b+1;
}

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

C++语言兼容C语言的代码
上面这段代码假如换成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("%d\n",*p);
    return 0;
}

在这里面相当于q知道i的地址,告诉p,关于上面传参数的括号,还是之前的知识点,&p在子函数里面修改了值之后在主函数进行调用,so,p前面加&,q前面不加
(ps:&必须紧紧挨着变量,不能分开)

上面这种写法是避免了二级指针(没听说过,完全蒙圈)
在这里插入图片描述
在这里插入图片描述
布尔类型
在这里插入图片描述
oj作业:
第一题:利用结构体实现读取输入和输出

#include <stdio.h>

typedef struct student{
    int num;
    char name[20];
    char sex;
}stu;
int main(){
    stu s;
    scanf("%d %s %c",&s.num,&s.name,&s.sex);
    printf("%d %s %c\n",s.num,s.name,s.sex);
    return 0;
    
}

要注意的点:初始化,写入和读取空格
第二题:
在这里插入图片描述

#include <stdio.h>
#include <cstdlib>


void modify_pointer(char *&p)
{
    p=(char*)malloc(100);//申请100个字节大小的空间
    fgets(p,100,stdin);
}
int main(){
    char *p=NULL;
    modify_pointer(p);
    puts(p);
    free(p);//申请的空间之后记得free
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值