C高级学习总结

课程涵盖了Linux操作系统基础,C语言的高级特性如结构体和指针,内存管理的malloc与free,位域和共用体,以及shell脚本的编写和命令使用。还涉及到文件系统、网络配置、软件管理和用户管理。此外,讲解了嵌入式系统概念和Linux发行版,以及shell编程中的条件判断和循环控制。
摘要由CSDN通过智能技术生成

课程安排

1天半:LinuxOS

1天:shell编程

3天:C高级(结构体、共用体、枚举、函数指针、指针函数、多文件编译、make工程管理)

day1

  1. 结构体
    1.  概念

是一类相关事物属性的集合,是一种自定义的数据类型

1.2 定义

struct 结构体名

{

属性1;

属性2;

....

属性n;

};

//描述一个人的姓名,年龄

struct people

{

char name[20];//姓名

int age;//年龄

};

定义了一个结构体,结构体的数据类型为struct people

1.3 定义一个结构体变量

数据类型 变量名;

int a;

struct 结构体名 变量名;

struct people p = {“zhangsan”,18};

 

1.4 访问

1.4.1 结构体变量名.成员

 

1.4.2 结构体指针变量->成员

数据类型 *指针变量名;

struct people *指针变量名;

 

 

1.5 字节对齐

字节对齐:一次性分配多少个字节

自然对齐(32OS):

char:1字节对齐

short:2字节对齐

int:4字节对齐

long:4字节对齐

float:4字节对齐

double:4字节对齐方式,分配的时候分配两次

注意:按照成员中最大的那个对齐

 

 

节省结构体空间的办法:

  1. 将成员中最大的放到最前面
  2. 位域or位段

未优化前:

 

优化之后:
/1字节8位,int 4字节,共32位

 

注意:不能使用标准输入对位域进行输入

day2

  1. 起别名

方法1:

 

方法2:

 

  1. 内存分区

 

  1. malloc和free

3.1 malloc

头文件:

#include <stdlib.h>

函数原型:

void *malloc(size_t size);

函数功能:申请空间

参数:要申请的空间的大小

返回值:成功返回申请到的空间的首地址,失败返回NULL

注意:

  1. malloc申请到的空间是没有名字的
  2. malloc申请到的空间是一片连续的内存空间

3.2 free

void free(void *ptr);

参数:申请到的空间的首地址

3.3 memset

头文件:

#include <string.h>

函数原型:

 

参数1:要填充的空间的首地址

参数2:要填充的字符

参数3:要填充的空间的大小

char buf[30] = {0};

while(1)

{

 memset(buf,0,sizeof(buf));//清空

         gets(buf);

}

day3

  1. 自定义头文件

.h文件

 

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

<>:编译器从系统库路径(/usr/include)下开始搜索头文件

  1. 文件编译

作用:避免头文件重复引用

#ifndef 标号(一般用大写表示,把.变成_)

#define 标号

  1. 头文件
  2. 宏定义
  3. 结构体类型的定义
  4. 枚举类型的定义
  5. 函数声明

#endif

  1. gcc编译流程

程序的编译要经历预处理、编译、汇编、连接四个阶段

方法1:

预处理(处理以#开头的文件):gcc -E stu.c -o stu.i

编译(生成汇编语言):gcc -S stu.i -o stu.s

汇编(将汇编语言转成机器代码):gcc -c stu.s -o stu.o

链接(将所有的机器代码汇集生成一个可执行文件):gcc stu.o -o stu

方法2:

将gcc的前四步合四为一

gcc stu.c -o stu

  1. 多文件编译(解决单独编译出错的文件)

多文件编译工作原理:

4.1 将gcc的前三个阶段合三为一

 

4.2 将所有的机器代码汇集生成可执行文件

  1. make工程管理器

make会在当前路径下找一个叫做Makefile/makefile(M大小写都可以)的文件

5.1 Makefile的命名规范

目标文件1:依赖文件1

(Tab键)依赖文件1是如何生成目标文件1

目标文件2:依赖文件2

(Tab键)依赖文件2是如何生成目标文件2

注意:

  1. 一个Makefile中可以有多个目标文件
  2. 如果两个目标之间没有依赖,系统默认只执行第一个目标

没有依赖关系:

有依赖关系:

 

 

  1. 执行make命令时,需要指定目标是什么,如果没有指定系统默认执行第一个目标文件
  2.  

 

  1. 目标文件可以没有依赖文件

 

5.2 解决假目标的办法

在最前面加上.PHONY(必须大写)

 

5.3 预定义变量

CC :编译器选项的名称,默认为cc

CFLAGS:编译器的选项,无默认值

RM:程序删除的名称,默认为rm -f

5.4 自定义变量

OBJ和OBJS,一个用于存放可执行文件,一个用于存放所有的依赖文件

5.5 自动变量

$@:目标文件

$^:所有的依赖文件

$<:第一个依赖文件

 

5.6 变量定义的两种方式

5.6.1 递归方式 VAR=var

 

注意:后面的值会影响前面的结果

5.6.1 简单方式 VAR:=var

 

5.7 嵌套Makefile

include(.h文件)、obj(*.o)、src(*.c)、bin(可执行文件)

1、先编写总控Makefile,书写自定义变量 or 预定义变量

 

2、进入src中编写Makefile,将所有的.c文件生成.o文件并且移动到obj中

 

3、进入obj中编写Makefile,将所有的.o文件生成可执行文件,并移动到bin目录中

 

  1. 编写总控Makefile,设置执行顺序,先执行src中的Makefile,然后再执行obj中的Makefile

 

6、枚举

使程序变得更加语义化

#define INPUT 1

#define OUTPUT 2

 

7、共用体

1.所有成员的首地址都是一致的

2.所占的内存空间的大小由成员中最大的那个决定

 

7.1 判断大小端

 

 

 

day4

 

  1. 递归

定规则自己执行

5!

  5 * 4!                   return 120

  4 * 3!             return 24

3 * 2!         return 6

2 * 1!     return 2

     1!   return 1

 

  1. gdb调试器

编辑器:vim、gedit

编译器:gcc

调试器:gdb

(1)编译的时候添加-g参数

gcc -g error.c -o error

  1. 启动gdb调试器

gdb error

  1. 设置断点

b main(从main函数开始调试)

b 行号

  1. 运行(r)
  2. 其它参数

n:下一步(不进入子函数)

s:下一步(进入子函数,包括库函数)

p a:打印a的值

c:跳出循环 or 函数

quit:退出

  1. 函数指针

定义一个指向整型的指针:int *p = NULL;

定义一个指向整型指针的指针:int **pp = NULL;

定义一个指向整型数组的指针,该数组有3个元素:int (*p)[3] = NULL;

struct student

{

char name[20];

int age;

};

定义一个指向结构体的指针:struct student *p = NULL;

int add(int m,int n);//数据类型:int (int,int)

定义一个指向函数的指针:int (*p)(int,int);

 

 

回调函数:

 

  1. 指针函数

返回值为指针的函数

 

  1. 什么是嵌入式

嵌入式系统是以应用为中心,以计算机技术为基础,并且软硬件可裁剪,适用于对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统

  1. Linux的发展史

 

  1. Linux的发行版本

 

  1. shell的类型

Bourne Shell: 最早的Shell

C Shell

Ksh

Z Shell

Bourne Again Shell (bash)

  1. shell

9.1 shell命令、shell、shell脚本的本质区别

shell命令:用户向内核发出的控制请求,与之交互的文本流

Shell是一个命令行解释器,将用户命令解析为操作系统所能理解的指令,实现用户与操作系统的交互。

shell脚本:一堆命令的集合

9.2 shell命令的格式

命令 [选项] [参数];

[]:表示可以省略

选项:功能

参数:操作的对象

注意:

  1. 三者之间必须有空格
  2. 若将多个命令写在一行,用分号隔开

(3)如果一条命令不能在一行写完,使用反斜杠(\)标明该命令未结束

9.3 用户系统相关命令

用户切换命令

su - 用户名;//切换用户,系统当前工作路径以及环境变量都会发生改变

su - 等同于 su - root

su root//切换到root用户,系统当前工作路径以及环境变量都未发生改变

注意:一般情况下不要切换到root用户,要使用的话在命令最前面添加sudo

9.4 系统管理命令

ps:显示当前系统中由该用户运行的进程的列表

ps -ef:查看所有进程及其(PID)进程号、系统时间、命令详细目录、执行者等

ps aux:除了可以显示ps-ef的内容外,还可以显示CPU及其内存的占用率

pstree:将所有的进程按照树状图显示

top:动态显示进程

ps axj

kill:输出指定的信号给指定的进程

kill -l:列出所有可用的信号名称

9.5 磁盘相关命令

fdisk:查看硬盘分区情况及对硬盘分区进行管理

fdisk -l:列出文件系统的分区情况

注意:使用fdisk的时候必须使用root权限

free:查看当前系统的内存使用情况

df:查看文件系统的磁盘空间占用情况

du:统计目录or文件所占磁盘空间的大小

day5

  1. 文件目录相关命令

LinuxOS下有7中文件类型:

  1. 普通文件  -
  2. 目录文件  d  //directory目录
  3. 字符设备文件 c
  4. 块设备文件 b  //block 块
  5. 链接文件 l
  6. 管道文件 p   //pipeline 管道
  7. 套接字文件(socket) s

 

1.1 chmod

作用:改变文件的访问权限

方式1:

u:文件拥有者

g:文件所属的用户组

o:其他人

a:所有者

+:增加权限

-:删除权限

=:设置权限

方式2:

-      rw-   rw-      r--    1 linux linux   126 7月  24 23:10

文件的类型     拥有者    用户所在组     其他人

注意:权限一般用8进制数表示  -表示没有权限,用0表示,有权限用1表示

rw- rw- r--

  1. 110 100  //664

r-x rw- --x

101 110 001  //561

    1.  chown

作用:修改文件所有者和组别

注意:使用时必须使用root权限

修改用户:

修改组:

同时修改用户和组:

1.3 chgrp

作用:修改用户所在组

注意:必须使用root权限

1.4 grep

作用:在指定的文件中搜索特定的内容

grep 字符串 文件名

-n :显示行号

1.5 alias

作用:起别名(一次性的),想要永久有效的话添加到.bashrc(家目录下)

1.6 wc

-l:统计这个文件有多少行

-c:统计这个文件有多少个字符

1.7 查看文件

cat 文件名;//只适合查看比较短的文档

more 文件名;//适合查看比较长的文档,按回车向下翻一行,按空格向下翻一页

less 文件名;//more的加强版,适合看比较长的文档,按回车向下翻一行,空格向下翻一页,支持上下箭头

2、特殊字符

*:匹配任意长度的字符串(任意个)

?:匹配一个长度的字符(任意一个)

[....]:匹配其中指定的一个字符

[ - ]:匹配指定的一个字符范围

[^...]:除了其中指定的字符,均可匹配

注意:以上指令只针对一个字符,*除外

2.1 管道

|:将前一个命令的输出作为后一个命令的输入

注意:一般不单独使用

2.2 输出重定向

> :如果文件不存在则新建,如果文件存在则清空文件中的内容

2.3 追加重定向

>>:如果文件不存在则新建,如果文件存在则追加在文件的末尾

2.4 输入重定向

2.5 将命令产生的错误信息输出到文件中

3、ln

3.1 硬链接

利用Linux中为每个文件分配的物理编号---inode建立链接

3.2 软链接(符号链接)

利用文件的路径名来建立链接,通常建立软链接使用的是绝对路径而不是相对路径

创建软链接:

创建硬链接:

软链接和硬链接的区别:

相同点:

ln命令会保持每一处文件的同步性,不论改动了哪一处,其它文件都会发生相同的变化

不同点:

软链接会在用户选定的位置上生成一个文件镜像,不会重复占用磁盘空间,平时用的最多的就是软链接

硬链接会在用户选定的位置上生成一个和源文件大小相同的文件。

4、压缩打包相关命令

4.1 压缩工具

gzip、bzip2

注意:以上只能压缩文件,不能压缩目录

压缩:

  1. gzip 文件名,压缩的后缀为 .gz
  2. bzip2 文件名,压缩的后缀为.bz2

解压:

方式1:

  1. gunzip 压缩后的文件名
  2. bunzip2 压缩后的文件名

方式2:

  1. gzip -d 压缩后的文件名
  2. bzip2 -d 压缩后的文件名

4.2 tar

作用:对目录进行打包或者解包,后缀为.tar

-c:打包

-x:解包

-v:显示详细的处理过程

-f:指定包文件名(该参数必须放在最后一个)

-z:调用gzip来压缩打包文件,与-x连用时调用gunzip完成解压缩

-j:调用bzip2来压缩打包文件,与-x连用时调用bunzip2完成解压缩

先打包

再压缩

先解压

再解包

将打包压缩一体化:

将解压解包一体化:

  1. Linux的环境变量

env:查看所有的环境变量

为什么所有的路径下都认识ls?

5.1 临时添加

注意:只对当前终端有效

5.2 永久添加

(1)sudo vim /etc/profile

(2)在文件末尾添加export PATH=$PATH:/home/linux/23071/linuxC/day5

(3)重启 or  source /etc/profile

重启:sudo reboot

关机:sudo shutdown -h now (立刻)  sudo shutdown -h +10 (10分钟后关机)

  1. Linux用户管理命令

6.1 相关配置文件

/etc/passwd:系统能够识别的用户清单

/etc/shadown:加密的用户清单,只有超级用户可以访问这个文件

/etc/group:包含了UNIX组的名称和每个组中的成员列表

6.2 创建用户

sudo adduser 用户名;

6.3 删除用户

sudo deluser --remove-home 用户名;

6.4 修改用户的密码

sudo passwd 用户名;

6.5 新建组

sudo groupadd 组名;

6.6 删除组

sudo groupdel 组名;

6.7 修改用户所在组

sudo usermod -g  目标组 要修改的用户;

  1. 共享文件

7.1 通过winscp

查看ip地址:ifconfig

登录winScp

注意:如果还是不行,添加网络适配器,并配置成仅主机模式

7.2 通过linux中的共享文件夹

(1)虚拟机-->设置-->选项

共享文件夹在/mnt/hgfs/

day6

  1. Linux的软件管理
    1. 换源

软件源配置文件/etc/apt/sources.list

    1. 下载
  1. sudo apt-get update //刷新软件源
  2. sudo apt-get install 包名
    1. 卸载

sudo apt-get remove 包名

    1. 测试网络

    1. 网络配置
  1. 虚拟机-->设置-->网络适配器

  1. 编辑-->虚拟网络编辑器

    1. linux下配置静态ip

    1. windows下配置静态ip

网络和internet设置-->更改适配器选项

  1. 网络基础知识介绍

IP地址:主机的唯一标识

2.1 IP地址的分类

A类IP地址:

由1字节的网络地址+3字节的主机地址,网络地址最高位必须是0

地址范围:1.0.0.0 ~126.255.255.255

B类IP地址:

2字节的网络地址+2字节的主机地址,网络地址最高位必须是10

地址范围:128.0.0.0 ~ 191.255.255.255

C类IP地址:

3字节的网络地址+1字节的主机地址,网络地址最高位必须是110

地址范围:192.0.0.0 ~ 223.255.255.255

D类

E类

2.2 子网掩码

作用:判断主机发送的包是向内网发送还是向外网发送

网络地址全是1,主机地址全是0

1111 1111  1111 1111  1111 1111  0000 0000

  255        255        255        0

192.168.0.10    192.168.2.12      192.168.0.2

&   255.255.255.0

192.168.0.0     192.168.2.0       192.168.0.0

2.3 网关

如果想向外网发送数据,就必须经过网关

2.4 DNS服务器

由解析器和域名服务器组成

注意:域名必须有一个IP地址,但IP地址不一定有域名

  1. shell脚本

一堆命令的集合

c语言(强类型语言,对数据类型分的很清楚),编译性语言 gcc 1.c  ./a.out

shell脚本(弱类型语言),解释性语言,不需要编译 ./1.sh

3.1 如何创建shell脚本

1、创建一个脚本文件,后缀为.sh

vim 1.sh

  1. 编辑shell脚本

  1. 执行时权限不够,需要人为的去添加

chmod 777 1.sh  or  chmod u+x 1.sh

  1. 运行

./1.sh

3.2 shell变量

3.2.1 自定义变量

shell允许用户建立  变量存储类型,但它不支持数据类型,任何被赋值给变量的值都被解释为一串字符。

命名规范:

  1. 由数字、字母、下划线组成,且开头不能为数字
  2. 在shell中变量一般用大写表示

注意:

  1. 等号的左右两侧不能有空格
  2. 去变量的值时,在变量前面添加$
  3. 在shell中,字符串用双引号或单引号都可以

3.2.2 位置参数

3.2.3 预定义变量

$#:包含命令行参数的个数

$@:包含所有的命令行参数

$*:包含所有的命令行参数

$?:包含前一个命令的退出状态,正常退出返回0,反之为非0 (shell中,0为真,非0为假)

$$:包含正在执行的进程号(PID)

案例1:在当前目录创建一个文件夹,如何判断该文件夹是否创建成功

案例2:在家目录创建一个叫做mydir的目录,在该目录中创建一个1.txt,然后向1.txt中写入”hello shell”

3.2.4 环境变量

env:查看所有的环境变量

3.3 shell程序和语句

3.3.1 说明性语句

#:注释

3.3.2 功能性语句

3.3.2.1输出

echo :自带换行

echo -n:不换行

3.3.2.2 输入

方式1:

方式2:

方式3:

方式4:

想要实现输出”hello shell “ ,”23071”

` `:反引号

3.3.3 expr

expr用于简单的整数运算,包括+、-、\*、/、%

注意:expr和变量以及变量和运算符之间必须添加空格

交叉编译工具链:

day7

  1. test

字符串、整数、文件属性

    1. 测试字符串

s1 = s2  测试两个字符串的内容是否完全一致

s1 != s2  测试两个字符串的内容是否有差异

-z s1 测试s1 字符串的长度是否为0

-n s1 测试s1 字符串的长度是否不为0

注意:[]的左右两侧必须有空格

    1. 测试整数

a -eq b  测试a与b是否相等

a -ne b  测试a与b是否不相等

a -gt b   测试a是否大于b

a -ge b  测试a是否大于等于b

a -lt b   测试a是否小于b

a -le b   测试a是否小于等于b

    1. 测试文件属性

-d name 测试name是否一个目录

-e name 测试name是否存在

-f name 测试name是否普通文件

-L name 测试name是否为链接文件

-r name 测试name文件是否存在且可读

-w name 测试name文件是否存在且可写

-x name  测试name 文件是否存在且为可执行

-s name   测试name 文件是否存在且其长度不为0

f1 -nt f2   测试文件f1 是否比文件f2 更新

f1 -ot f2   测试文件f1 是否比文件f2 更旧

  1. shell控制语句

2.1 选择语句

2.1.1 单分支选择

if [ 表达式]

then

语句

fi

2.1.2 双分支选择

if [ 表达式 ]

then

语句1

else

语句2

fi

2.1.3 多分支选择

if [表达式1]

then

语句1

elif [表达式2]

then

语句2

...

elif [ 表达式n ]

then

语句n

else

语句n+1

fi

2.1.4 case

case 字符串变量 in

模式1)

命令表1

;; //类似与break,但是;;不能省略,最后一个可以省略

模式2 | 模式3)

命令表2

;;

.........

模式n)

命令表n

;;

     *)//类似于c中的default

命令表n+1

;;

esac

2.2 循环语句

2.2.1 for语句

for 变量 in 单词表

do

语句

done

方式1:

方式2:

方式3:

方式4:

注意:{ }内不能写变量

方式5:

2.2.2 while语句

while [表达式]

do

语句

done

案例:打印9*9乘法口诀表

break n:跳出n层循环

continue:结束本次循环,开始下一次循环

3、函数

方式1:

函数名()

{

}

方式2:

function 函数名()

{

}

调用:

方式1:

变量=`函数名 形式参数列表`

注意:函数中的所有标准输出传递给了主程序中的变量

方式2:

函数名 形式参数列表

echo $?

案例:

  1. 判断用户主目录是否有file-dir和dir-dir目录

如果这两个目录存在,询问是否删除这两个目录

如果用户的是Y,将这两个目录删除,重新创建这两个目录

如果是N,取消删除

如果上述的目录不存在,则创建这两个目录

  1. 请用户输入一个路径,将这个路径下的文件拷贝到file-dir这个目录,将

这个路径下的目录拷贝的dir-dir目录

  1. 统计拷贝的文件和目录的个数

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值