C高级知识点梳理

C高级

递归函数

概念:重复调用其他函数或者调用自己,但是调用的时候一定要注意结束调用的条件。
如何编写一个标准的递归函数?
三要素:
(1)从哪里开始?
(2)从哪里结束?
(3)每一步干什么?

递归函数

斐波那契数列

回调函数

概念:把B函数的地址即(函数名或者&函数名)作为A函数的参数,传递给A函数,在A函数中通过使用这个参数来间接调用B函数的过程就称为“回调函数”

回调函数

函数和指针的结合

函数:存在于内存中的一段二进制代码,函数名代表函数的入口地址,程序运行的时候会为函数体寻找一片空间,又因为指针变量是用来存储变量地址,故可以让指针存储函数的地址,将这样的指针成为“函数指针”

指针函数

概念:函数返回值类型是指针类型的函数

函数指针

函数指针

概念:指向函数的指针(函数的本质是存在内存中的一段二进制代码,因此会占据一片空间,同时该片空间的首地址用函数名来代替)

定义方式:
如何定义一个指向整型的指针?
–》int *p

如何定义一个指向含有5个int类型元素的一维数组?
–》int *(pArr)[5];

定义函数指针方式:
返回值类型(*pFunc)(形参列表);

void func(int arr[20]);//这里的[]就是*号,只是允许用户可以这样去写,所以等价于这里写的arr就是一个指针变量。
void func(int *arr) sizeof(arr) = 8 ;

函数指针数组

概念:数组元素类型是函数指针类型的数组。

定义:
函数指针类型 数组名【元素个数】;//取完别名后可这样定义函数指针数组
返回值类型 (*数组名【元素个数】)(参数列表);

返回值数据类型一致,参数的个数与数据类型也一致(比如两个整形数的加减乘除运算)
函数指针数组

动态内存管理

针对:堆区

在堆区中:常见的操作有—》申请空间,释放空间,初始化空间

因此:以上操作全局需要借助于函数来实现:
申请空间:malloc calloc
释放空间:free
初始化空间:memset
扩容空间:realloc

头文件:
#include<stdlib.h>
函数原型:

        1.void *malloc(size_t size);  
        功能:申请空间在堆区中  
        参数:所需申请空间占据的字节数  
        返回值:成功返回连续空间的首地址,失败返回NULL

        2.void *calloc(size_t nmemb,size_t size);
        功能:申请空间  
        参数:  
            参数1:所需申请的元素个数  
            参数2:元素的大小(字节数)
        返回值:成功返回连续空间的首地址,失败返回NULL
        注意:calloc在申请完空间之后,会自动将申请的连续空间初始化为'\0'
        
        3.void free(void *ptr);
        功能:释放空间
        参数:所需释放空间的首地址
        返回值:无返回值

        4.void *realloc(void *ptr,size_t size);  
        功能:用来扩容空间  
        参数:  
            参数1:所需扩容空间的首地址(malloc的返回值)
            参数2:扩容之后总的字节数(旧+新)
        返回值:成功返回扩容之后的空间首地址,失败返回NULL
        注意:扩容之后的空间首地址可能和之前的地址一样,也可能不一样。

       #include <string.h>

       5.void *memset(void *s, int c, size_t n);  
       功能:用来重置一片内存空间(当作清空空间居多!)    
       参数:  
            参数1:所需重置内存空间首地址  
            参数2:所需重置的字符---》'\0',0    
            参数3:所需重置内存空间的大小---》sizeof()

结构体

概念:是一种构造数据类型,目的是为了将一个事物的多重属性表示清楚(属性可能是不同的数据类型,也可以是相同的数据类型)。

如何构造一个结构体类型?

struct 结构体名
{
    数据类型1 成员1;
    数据类型2 成员2;
    ...
    数据类型N 成员N;
};

如何定义结构体变量?
struct 结构体名 变量名;

如何给结构体成员进行赋值?
变量名={值1,值2···};
struct 结构体名 变量名={值1,值2,···};

如何访问结构体中的成员?
方式一:变量名.成员名;
方式二:结构体指针->成员名;

定义结构体数组,实现对于一批数据的输入输出。

typedef

typedef:给已存在的一个数据类型在其作用域内取一个别名

用法:
typedef 类型名 新类型名;

注意:对于基本类型可以按照以上取别名的方式去写,但是对于函数指针类型需要用以下的的方式进行定义。

eg:
typedef int MYInt;
MYInt a;

注意:
针对函数指针类型取别名写法:
返回值类型 (*新类型名)(形参列表);

eg:构体嵌套的输入输出

#include<stdio.h>

typedef struct tearcher
{
    char sex[20];
    int age;
}TEAR;

typedef struct student
{
    char name[20];
    int phone;
}STU;

typedef struct class 
{
    TEAR tearcher;
    STU student;
    int room;
    int number;
}CLASS;

int main(int argc, char const *argv[])
{
    CLASS a={0};
    scanf("%s%d%s%d%d%d",a.tearcher.sex,&a.tearcher.age,a.student.name,&a.student.phone,&a.room,&a.number);
    printf("教师性别:%s\t年龄:%d\n学生姓名:%s\t电话:%d\n教室编号:%d\t班级人数:%d\n",\
    a.tearcher.sex,a.tearcher.age,a.student.name,a.student.phone,a.room,a.number);
    return 0;
}

枚举

概念:跟宏比较类似,意味着也是一些常量值,只不过这些常量值是被放在一个集合里面。

如何定义一个枚举类型?

enum 枚举名(一般大写)
{


};

enum ERRORNU
{
    ERROR1,
    ERROR2,
    ERROR3
};

字节对齐

概念:在申请结构体空间时,会遵循“字节对齐”的原则!

什么是字节对齐?
—》分类讨论

第一点:考虑在范围之内的成员必须为基本数据类型!

在32OS:系统最多一次性开辟4个字节
怎样确定每一次开辟的空间大小,依赖于成员中占据字节空间最大的那个数据类型,将其作为基准,来进行每一次空间大小的开辟,但是成员有超过上限4字节的数据类型,此时仍按照4字节进行开辟空间。反之,则按照那个最大的类型占据字节数进行开辟。

在64OS:系统最多一次性开辟8个字节
怎样确定每一次开辟的空间大小,依赖于成员中占据字节空间最大的那个数据类型,将其作为基准,来进行每一次空间大小的开辟,但是成员有超过上限8字节的数据类型,此时仍按照8字节进行开辟空间。反之,则按照那个最大的类型占据字节数进行开辟。

第二点注意:
不管是32OS还是64OS,在存储成员时,均需要保证存储的地址编号和该成员自身的数据类型大小成整数倍的关系,否则往后寻找下一个合适的地址空间进行存储。
因此结合以上两点来确定结构体类型占据的字节数!!!

思考:

案例1:
typedef strut AA
{
    int a;
    char b;
    short c;
}Type1;
printf("sizeof(Type1)=%ld\n",sizeof(Type1));
结果:8字节

typedef strut AA
{
    int a;
    char b;
    short c;
    char d;
}Type1;
printf("sizeof(Type1)=%ld\n",sizeof(Type1));
结果:12字节

typedef strut AA
{
    char b;
    int a;
    short c;
}Type2;
printf("sizeof(Type3)=%ld\n",sizeof(Type3));
结果:12字节

案例2:
typedef strut AA
{
    int a;
    char b;
    short c;
    double d;
}Type1;
printf("sizeof(Type4)=%ld\n",sizeof(Type4));
结果:16字节

案例3:验证存储结构体成员时,会考虑到地主编号和成员数据类型大小成整数倍的关系

字节对齐1

字节对齐2

共用体

概念:多个成员共用同一片空间,因此开辟内存空间时,会按照占据内存空间最大的数据类型进行开辟。

定义格式:

union 共用体名
{
    数据类型1 成员1;
    ...
    数据类型N 成员N;
};

注意:共用体的使用方法和结构体一致,唯一区别是:结构体的成员空间是独立的,而共用体的成员共用同一片空间。

共用体

大小端(字节序)

概念:计算机中存储数据的时候到底将低字节或者高字节处的内容存储在低地址还是高地址的问题。

大端存储:低字节处的内容存储在高地址处,高字节处的内容存储在低地址处。
小端存储:低字节处的内容存储在低地址处,高字节处的内容存储在高地址处。

低字节:一串二进制数据的右边
低地址:小的地址编号

大小端1

代码:共用体验证大小端存储的问题

大小端2

多文件编译

头文件的书写

格式:条件编译—》防止同一个头文件被重复定义
创建一个后缀.h文件 eg: touch test…h
打开test.h —>vim test.h
编写以下代码:

#ifndef _TEST_H
#define _TEST_H

...

1.宏定义
2.结构体定义
3.取别名
4.全局变量声明
5.函数声明
6.枚举类型定义

#endif

之前:书写代码需要一个C文件即可
现在:
具备书写一个项目的思想
项目是什么样的?
–》会有很多不一样的需求,因此每一个需求可能会交给一个人去完成,因此书写一个完整的项目需要多个人去负责,意味着会有多个.c文件需要进行书写,也需要有一个.h文件作为辅助,进行编译。
注意:对于以上需求,需要通过主文件进行调用—》.c文件
综上:
1个主文件+若干个子文件+1个头文件

Make

概念:工程管理工具
可以将很多.c文件和.h文件进行统一管理

使用:
命令行输入 make 目标名 即可

如何编写要给Makefile文件?
—》
目标:依赖
【Tab】命令表
目标:需要生成的文件
命令表:将依赖转换成目标
依赖:源文件

嵌套Makefile:

makefile

make中的一些变量

(1)用户自定义变量
格式:
变量名:=值(定义变量且赋初值,变量名建议大写)

(2)自动变量

$<:依赖中的第一个依赖
$^:所有依赖  
$@:目标名

(3)系统预定义变量
CC:编译器名称,默认值是cc,用户可以自己赋值为gcc eg: CC:=gcc
CFLGAS:编译器的选项,无默认值,用户可以自己赋值: eg:CFLGAS:=-c -g -Wall
RM:代表删除,默认值为:rm -f,用户可以自己赋值为rm -rf eg: RM:=rm -rf

makefile1

makefile2

makefile3

(4)环境变量
export:添加一些指定的环境变量到整个系统环境中去
eg: export 变量1 变量2 变量3

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值