C高级及shell脚本学习归纳笔记

目录

day1 操作系统、硬盘分区、分区格式、Linux文件系统

1、操作系统

2、硬盘分区

3、分区格式

4、Linux文件系统,目录与分区的关系

day2 linux命令

1、chmod

2、linux文件类型

3、IP地址、子网掩码、网关、DNS服务器

4、永久修改环境变量

5、软硬链接

day3 环境变量、$PATH、输入输出

1、环境变量

2、$PATH

3、输入输出

4、shell中的逻辑运算符,在test语句中的应用

5、$与命令的结合

day4 结构体

1、&和.的优先级

2、*和.的优先级

3、&和->的优先级

4、结构体变量名的理解

5、对malloc函数返回值强制转换的理解

6、void 指针

7、栈区内存自动分配规则

8、size命令

day5 自定义头文件、gcc编译器原理、多文件编译

0、头文件中的内容

1、自定义头文件和库头文件的区别

2、自定义头文件和库头文件在程序文件中多次引用的区别

3、条件编译

4、gcc编译过程

5、预定义符号

7、makefile文件(脚本)的执行逻辑

day 6 函数指针

1、函数指针来源

2、函数指针数组

3、函数指针作为另一个函数的参数(回调函数)

4、给函数指针类型取别名

5、静态区域变量的内存分配时间

6、存储类型(重点介绍extern 和 static)

1、auto

2、register

3、extern

1、extern 修饰全局变量

2、extern 修饰函数

4、static

1、static 修饰全局变量

2、static 修饰函数

3、static修饰局部变量

7、大小端序

小端序:

大端序:

8、字节对齐(数据对齐)


day1 操作系统、硬盘分区、分区格式、Linux文件系统

1、操作系统

概念:

操作系统OS是管理和控制计算机硬件与软件资源的计算机程序,它是直接运行在“裸机”上的最基本的系统软件,任何其它软件都必须在操作系统的支持下才能运行(函数库,运行库),换句话说,操作系统是用户和计算机的接口,同时也是计算机硬件和其它软件的接口。

总之,操作系统位于底层硬件与用户之间,是两者沟通的桥梁,用户通过操作系统的用户界面输入命令;操作系统则对命令进行解释,驱动硬件设备,实现用户的需求。

主要组成:

1、驱动程序

驱动程序是操作系统最底层的、直接控制和监视各类硬件的部分,它们的职责是隐藏硬件的具体细节,并向其它部分提供一个抽象的、通用的接口。

2、内核

操作系统最核心部分,包括:内存管理、进程管理、文件系统管理、设备管理等核心单元。

3、接口库

接口库是一系列特殊的程序库,它们的职责在于把系统所提供的基本服务包装成应用程序所能使用的编程接口(API),因而是靠近应用程序的部分

4、外围

是指操作系统中除上述3部分以外的所有其它部分,通常用于提供特定高级服务的部件。

2、硬盘分区

硬盘分区是针对一个硬盘进行操作的,它可以分为主分区、扩展分区、逻辑分区。

主分区是包含操作系统启动所必须的文件和数据的硬盘分区,要在硬盘上安装操作系统,则该硬盘必须要有一个主分区,而且其数量可以是1~3个;

扩展分区也就是出主分区外的分区,但它不能直接使用,必须再将它划分为若干个逻辑分区,其数量可以有0个或1个;

而逻辑分区在数量上没有什么限制。

3、分区格式

4、Linux文件系统,目录与分区的关系

linux:目录包含分区或其它存储设备

Windows:分区或其它存储设备包含目录

day2 linux命令

1、chmod

2、linux文件类型

3、IP地址、子网掩码、网关、DNS服务器

4、永久修改环境变量

1、/etc/profile 修改整个系统的环境变量,完事后,无论哪个用户进来都可以使用其中的环境变量

2、/home/某user/.bashrc 修改某用户的环境变量,完事后,只有这个用户可以用其中的环境变量

5、软硬链接

一.软链接

①软链接的概念:

类同与windos的快捷方式,给文件创建一个快速的访问路径,它依赖于原文件,与普通文件没什么不同,inode 都指向同一个文件在硬盘中的区块。当原文件出现问题后,该链接不可用。

(1)可以应用于目录

(2)可以跨文件系统

(3)不会增加被链接文件的链接次数

(4)大小为指定的绝对路径所包含的字符总数

(5)有自己的inode号

(6)权限无关紧要

②如何实现软链接:

命令 ln -s

下面我创建了一个file1的文件,并指定它软链接到 /mnt路径下的file2 。

查看file2,可以发现内容与file1的内容一致。

当删除file1时,file2失效。

[root@localhost /]# touch /opt/file1
[root@localhost /]# touch /opt/file1  >123abc
[root@localhost /]# rm -rf  /opt/file1
[root@localhost /]# touch /opt/file1
[root@localhost /]# echo 123abv > /opt/file1 
[root@localhost /]# ln -s /opt/file1  /mnt/file2
[root@localhost /]# cat /mnt/file2 
123abv
[root@localhost /]# rm -rf /opt/file1 
[root@localhost /]# ll /opt/file1 /mnt/file2 
ls: 无法访问/opt/file1: 没有那个文件或目录
lrwxrwxrwx. 1 root root 10 11月 27 13:12 /mnt/file2 -> /opt/file1
[root@localhost /]# cat /mnt/file2 
cat: /mnt/file2: 没有那个文件或目录

二.硬链接

①硬链接的概念:

指通过索引节点来进行连接。在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点号(Inode Index)。在Linux中,多个文件名指向同一索引节点是存在的。一般这种连接就是硬连接。硬连接的作用是允许一个文件拥有多个有效路径名,这样用户 就可以建立硬连接到重要文件,以防止“误删”的功能。其原因如上所述,因为对应该目录的索引节点有一个以上的连接。只删除一个连接并不影响索引节点本身和 其它的连接,只有当最后一个连接被删除后,文件的数据块及目录的连接才会被释放。也就是说,文件真正删除的条件是与之相关的所有硬连接文件均被删除。

(1) 硬链接,以文件副本的形式存在。但不占用实际空间。

(2) 不允许给目录创建硬链接。

(3) 硬链接只有在同一个文件系统中才能创建。

(4) 删除其中一个硬链接文件并不影响其他有相同 inode 号的文件。

②如何实现硬链接:

命令 ln

下面我创建了一个file1的文件,并指定它硬链接到 /mnt路径下的file2 。

查看file2,可以发现内容与file1的内容一致, inode也一致 。

当删除file1时,file2正常使用。

[root@localhost /]# rm -rf /mnt/file2 
[root@localhost /]# touch /opt/file1
[root@localhost /]# echo 658bcd  > /opt/file1 
[root@localhost /]# ln  /opt/file1  /mnt/file2
[root@localhost /]# ll /opt/file1 /mnt/file2 
-rw-r--r--. 2 root root 7 11月 27 13:21 /mnt/file2
-rw-r--r--. 2 root root 7 11月 27 13:21 /opt/file1
[root@localhost /]# rm -rf /opt/file1 
[root@localhost /]# ll /opt/file1 /mnt/file2
ls: 无法访问/opt/file1: 没有那个文件或目录
-rw-r--r--. 1 root root 7 11月 27 13:21 /mnt/file2
[root@localhost /]# cat /mnt/file2 
658bcd

day3 环境变量、$PATH、输入输出

1、环境变量

每个用户的环境变量(env)、shell版本都是独立的,比如有的用户在创建时继承了/etc/skel文件夹下的配置文件,他的shell版本就是该文件夹下的bash(bourne again shell),$PATH $HOME等都是环境变量

2、$PATH

3、输入输出

4、shell中的逻辑运算符,在test语句中的应用

方法1

方法2:

5、$与命令的结合

$变量 是取变量的值

$(command) 是取命令的结果

与 echo `pwd`效果是一样的

day4 结构体

1、&和.的优先级

&比.优先级高,所以不用&(s1.height)

2、*和.的优先级

.比*优先级高,所以用实例指针访问成员时,必须用()

3、&和->的优先级

->比&优先级高,所以 &ps->name可以直接使用

4、结构体变量名的理解

5、对malloc函数返回值强制转换的理解

6、void 指针

7、栈区内存自动分配规则

比如我们定义一个结构体类型

typedef struct student
{
	char name[29];
	int age;
	float scores[4];
}STU;
int main(void)
{
	STU s1;
	printf("%d\n", sizeof(s1)); 
}

输出的结果是52,而不是29+4+4*4=49

这是因为内存在自动分配时,总是4字节4字节的分配,所以当给s1实例的name字符数组变量分配到第29个字节时,其实是直接给了32个字节,然后第33个字节分配给Int的age变量

8、size命令

size命令主要用于查看程序文件的代码段、数据段和BSS(未初始化的数据)段的大小以及总体文件大小

text:代码段

data:初始化的全局变量和static变量

bss:未初始化的全局变量和static变量

dec:该文件的总体大小,十进制

hex:该文件的总体大小,十六进制

day5 自定义头文件、gcc编译器原理、多文件编译

0、头文件中的内容

1、自定义头文件和库头文件的区别

“”和<>的区别:

“”:编译器从用户的工作路径开始搜索头文件

<>: 编译器从标准库路径开始搜索头文件

2、自定义头文件和库头文件在程序文件中多次引用的区别

如果自定义头文件中没有使用条件编译,那么在.c文件中多次引入该自定义头文件时进行编译,会出现宏、结构体、函数声明等的重复定义错误

而库头文件因为使用了条件编译,所以在.c文件中多次重复引入库头文件时进行编译,依然不会出现错误

3、条件编译

解决2中的问题,可以使用条件编译的方法来避免因为多次引入头文件而带来的重复定义问题

语法:

#ifndef _FILE_H //一般与头文件名同名,大写

#define _FILE_H //一般与头文件名同名,大写

//1 库头文件名

//2 宏定义

//3 结构体类型的定义

//4 枚举类型的定义

// 5 函数声明

#endif

4、gcc编译过程

5、预定义符号

在头文件中,通常包含一些预定义的宏,宏在预处理时执行宏替换(宏展开),宏是用户自定义的。

而在c语言中,有一些预处理定义的符号串,它们的值是字符串常量、或者是十进制数字常量、在预处理阶段就将自动进行替换

7、makefile文件(脚本)的执行逻辑

1、首先检查文件中的所有依赖关系,是否存在两层以上的依赖,如果存在,则判断下层的目标和先决条件的时间戳哪个更新,如果下层的目标更新,则下层的规则命令不会执行,如果下层的先决条件更新,则执行下层规则的命令来重构下层目标。等待所有的下层规则全部检查(并执行命令,这些命令可能全都不会执行)完毕,就回到上层的依赖,检查其目标和先决条件的时间戳哪个更新,目标更新,则不会执行命令去重构目标,如果先决条件中有一个比目标更新,则执行命令去重构目标。

2、当目标是假文件时,因为目录中根本没有这个名称的文件,那么“make 假文件“时,其规则中的命令每次必执行。

day 6 函数指针

1、函数指针来源

函数:int fun(int, int);

函数的首地址:&fun

函数指针指向该函数的首地址:int (*pfun)(int, int) = &fun

可以得出:(*pfun)= fun

所以,函数的调用可以从fun() --->*pfun()

又因为C语言规定,函数名即是函数的首地址,所以函数名就是函数的指针

那么我们又可以得出,fun()------>pfun()

2、函数指针数组

存储函数指针的数组即是函数指针数组,与字符数组的存储方式一样

声明形式:

比如要存储的函数类型为 int (int, int)

那么此函数指针数组应该这样声明: int (*pfunarry[5])(int, int)

3、函数指针作为另一个函数的参数(回调函数)

一个函数指针的类型为:int (*)(int, int)

另一个函数的类型为 int (int (*)(int, int), int)

在这个函数中,第一个参数就是函数指针

所以,在执行这个函数时,可以通过传入的函数指针去执行其指向的函数,如果函数指针参数指向的函数的返回值类型与外函数的返回值类型一致,那么母函数就可以作为回调函数。

4、给函数指针类型取别名

因函数指针的类型过长,所以可以用typedef给其取别名

比如,上面的函数指针类型为,Int (*)(int, int)

那么我们可以给其取别名,格式为:

type int (*PFUN)(int, int); // int (*)(int, int) -----------> PFUN

那么第1点中,定义一个此类型的函数指针,就可以简写为:

PFUN pfun;

那么第2点中,定义一个元素为此类型的函数指针数组,就可以简写为:

PFUN pfun[5];

那么第3点中,给外函数传进去的参数就可以简写为:

int pfunction(PFUN, int, int); //函数声明

5、静态区域变量的内存分配时间

6、存储类型(重点介绍extern 和 static)

1、auto

auto是默认缺省的变量存储类型

2、register

用register修饰的变量存储在寄存器内,其读写速度是最快的,但是因为拿不到它的地址,所以用的情况也较少。

3、extern

1、extern 修饰全局变量

当多文件编译时,一个文件可能会用到别的文件中的全局变量,只需要在想用别文件全局变量的文件的所有函数之外,用extern声明同名的全局变量,即可做到全局变量的外部声明。

2、extern 修饰函数

与修饰全局变量作用一致,当多文件编译时,一个文件中想调用另一个文件中定义的函数,此时有两种方法,可以将存在函数声明的头文件加注在第一个文件中即可正常调用;

另外一个方法就是在所有函数之外使用extern 声明外部文件中的函数,这样就可以调用别的文件中的函数。

4、static

1、static 修饰全局变量

多文件编译时,如果一个文件中的全局变量不想被其它文件访问,只需要在该全局变量之前用static修饰,就可以实现该目的。与extern修饰全局变量的作用正好对立

2、static 修饰函数

多文件编译时,如果一个文件中的某函数不想被其它文件调用,只需要在该函数声明和定义之前用static修饰,就可以实现该目的。即使别的文件中有该函数的声明头文件或者extern 声明的该函数,也不能改变static 的目的。与extern修饰函数的作用正好相反

3、static修饰局部变量

局部变量的作用域因为其存在时间的关系,只作用于定义到最近的大括号这个代码段内,出了这个代码段,其内存空间将被释放,如果我们想要在这个代码段之外访问这个局部变量的值,只需要在声明定义局部变量时,用static进行修饰,就可以做到。

7、大小端序

小端序:

低字节存储在低地址,高字节存储在高地址

大端序:

低字节存储在高地址,高字节存储在低地址

8、字节对齐(数据对齐)

所有的变量在内存中的存储都遵循 自然对齐规则,以提高数据访问速度

在结构体变量(实例)中,它不仅遵循自然对齐规则,内存分配的步长是以其数据长度最大成员为准的,比如最大成员是个double,那么在分配时就按8byte进行分配,有时这种规则会引起内存的浪费,所以在结构体定义中,我们为了避免这种浪费,通常按照数据长度由大到小的顺序来声明

这是各种成员顺序不同的结构体变量在内存中的存储位置:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值