一、前言
0.为什么虚拟机?
Windows上实现另一个操作系统(Windows、Linux、macOS、Android)
1.linux操作系统有什么用?能干嘛?有什么优点吗?
linux操作系统设计的三大领域:
linux嵌入式开发工程师
服务器端
Pc桌面
优点:
Windows 不免费,不开源(代码你看不见)
linux 不免费,开源(代码你能看到) 企鹅
2.ubuntu
可以理解为模拟器。pc图形化界面
3.C语言,为什么嵌入式要学c语言?
嵌入式 是一个硬件(15%~30%)、软件()相结合。
编程语言中,只要C语言可以去高效的操作硬件,原因是c语言里面有指针(精华)
二、指令
1.打开终端
1.点击图标
2.右键-打开终端
3."ctrl"+"alt"+"t"
2.关闭终端
1.点击x开闭
2."ctrl"+"d"
3.exit 退出用户
3.调节字体
放大 "ctrl" + "shift" + "+"
减小 "ctrl" + "-"
4.ubuntu@ubuntu:~$
ubuntu@ubuntu:用户名 连接符 主机名
:~ 家目录
$ 普通用户
# 超级用户 root
切换用户:
su root 切换到超级用户
如果root的密码不知道:
修改密码: sudo passwd root
5.查看文件
ls 查看当前目录下的文件(目录)
ls -lh 查看文件的详细信息
ls -a 查看文件且包含隐藏文件 .名字 隐藏文件 . 当前 .. 上一级
ls -i 查看文件的inode号(编号)
ls -ai 查看隐藏文件并且查看编号
6.d rwxr-xr-x 2 ubuntu ubuntu 4.0K 12月 13 10:02 111
d 目录文件
- 普通文件
b 块设备驱动文件 例如:磁盘、硬盘
c 字符设备驱动文件 例如:鼠标、键盘
s 套接字文件 进程之间通信使用的
p pipe 管道文件
l 链接文件
bcd-lsp
rwxr-xr-x
r(读) w(写) x(可执行) -(无权限)
三个用户
文件所属用户(u) 文件所属组用户(g) 其他用户(o)
rwx r-x r-x
修改权限
chmod 用户缩写 +、- 权限字符 文件名
示例: chmod g + w 文件名
八机制的权限 默认权限0775(0代表的是八进制) 或者775
chmod 八进制权限 文件名
示例: chmod 0775 文件名
八进制数 0~~7
0 无权限
1 可执行权限
2 可写权限
3 可写可执行权限
4 可读权限
5 可读可执行权限
6 可读可写权限
7 可读可写可执行
2 文件个数
ubuntu ubuntu 文件所属用户 文件所属组用户
4.0k 文件的大小,以字节为单位 4096/1024 = 4kb
12月 13 10:02 文件最后的修改日期
111 目录名、文件
7.清屏
ctrl +l
clear
8.cd
切换目录 相当于Windows下双击文件夹
格式: cd 路径/目录名 ,但是路径看情况是可以省略的
进入到当前目录 cd Desktop cd ./Desktop
返回上一级 cd ..
切换到当前目录就是不变 cd .
返回家目录 cd cd ~
返回上一次的路径 cd -
切换到根目录 cd /
绝对路径 从根目录开始查找 cd /usr/include
相对路径 通过目录间的相对位置的关系进行查找
9.创建目录
mkdir 路径/目录名
示例: mkdir 22121班级 默认权限 775
mkdir -p 路径/目录1/路径/文件2...
mkdir -p day2/day3/day4/day5
不需要默认权限了
mkdir -m 八进制权限 路径/目录名 指定权限创建
示例: mkdir -m 0664 ./day2
10.删除目录
删除空目录
rmdir 路径/目录名
示例:
rmdir ./day1
11.创建文件
touch 路径/文件名
示例:
touch 1.c
touch 2.c ./day2/2.txt
12.删除文件
rm 路径/文件名 删除普通文件
rm -r 路径/目录名 强制文件
* 通配符
linux 目录这块 * 代表任意
rm *.c 删除所有同类型的文件
13.拷贝
cp 拷贝
文件的操作
格式:
cp 路径/文件名 目标路径/文件名
示例:
cp 路径/文件名 目标路径/文件名(重命名)
目录的操作
格式:
cp 路径/目录名 目标路径/目录名(重新的目录名)
14.移动
mv 移动
格式:
mv 路径/文件名 目标路径 移动文件
格式:
mv 路径/文件名 目标路径/重命名 移动的同时并且重命名
15.练习
1、在家目录下创建mydir目录
mkdir ./mydir
2、将根目录下的etc下的passwd文件和group文件复制到mydir目录下
cp ./../../etc/passwd ./../../etc/group ./mydir/ -r
3、把mydir下的passwd文件改名为pw.txt,将group文件改名为gp.txt
mv mydir/passwd mydir/pw.txt
mv mydir/group mydir/gp .txt
4、在mydir目录中嵌套创建dir2/dir3/dir4/dir5
mkdir mydir/die2/dir3/dir4/dir5 -p
5、将mydir目录下的pw.txt拷贝到dir2/dir3中,将gp.txt文件移动dir2/dir3/dir4中
cp mydir/pw.txt mydir/die2/dir3/
mv mydir/group mydir /die2/dir3/dir4/
6、查看dir2/dir3/dir4中文件的详细信息
ls -Th mydir/die2/dir3/dir4/
7、将家目录下的mydir文件删除
rm mydir -r
16.查看代码
cat 文件名
cat 1.c
cat 5.c >> 6.c 将5.c的内容追加到6.c中
17.echo
终端打印
一般情况下,使用,shell脚本(C高级)
echo 1
三、vim编辑器
1.为什么使用vim ?
1.关键字会高亮显示
2.可以不用鼠标,直接完成代码的编写
3.没有补全功能
2.打开vim编辑器
touch 1.c
vim 文件名 vi 文件名 如没有保存,就直接退出,不会有任何显示
3.vim的三大模式
1.命令行模式
打开vim编辑器时,自动进入vim编辑器的命令行模式
其他模式进入到命令行模式---->Esc
主要功能:复制、粘贴、剪切、撤销、行间跳转、查找
1).复制
yy 复制一行,复制光标所在行
nyy n代表复制的行数
2)粘贴
p 粘贴到光标所在下一行
3)剪切
dd 剪切一行
ndd 剪切n行
dG 从光标所在行删除的尾行
dgg 从光标所在行删除的首行
d0 从光标位置删除到行首
d$ 从光标位置删除到行尾
4)撤销 u
反撤销 ctrl + r
5)行间跳转
G 跳转到尾行
gg 跳转到首行
nG n代表的是第n行
0 跳转到行首
$ 跳转到行尾
6)格式化对齐
gg = G
nG = mG 格式化n到m行
鼠标选中需要对齐的代码,按下=
2.插入行模式
a 从光标的后一位插入
A 从光标的所在行的行尾插入
i 从光标的前一位插入
I 从光标的所在行的行首插入
o 从光标所在行的下一行插入
O 从光标所在行的上一行插入
3.底行模式
在插入行模式下,按下esc键,回到命令行模式,按下"shift" + ":"
在命令行模式下,按下空格键
:w 保存
:q 退出
:wq 保存并且退出
:q! 强制退出
:x 保存并退出
:wqa 全部保存并退出
:vsp 文件名.c 水平分屏
:sp w文件名.c 垂直分屏
退出分屏 是使用vim编辑器的操作
查找、高亮显示
/word word 要查找的单词
n 向下查找
N 向上查找
:noh 取消高亮
:set number :set nu 临时显示行号
:set nonumber :set nonu 临时隐藏行号
4.可视模式
可视模式---->命令行模式 按两下esc 快速切换到命令行模式
可视模式---->插入行模式 shift + (i、o、a等)
从window下复制到linux 下 ctrl +shift +v
从linux 下 复制到window 下,按下shift 鼠标选中想要复制的内容,右键,复制
分屏
ctrl + shift +e 水平
ctrl +shift +o 垂直
退出分屏的终端 ctrl + d
四、C语言基础
1.第一个c语言程序
Inc tab键 补全头文件
main tab键 补全主函数
#include <stdio.h>
#include "stdio.h"
int main(int argc, const char *argv[])
{
printf("hello world\n");//打印hello word
return 0;
}
# 预处理标识符
#include 包含头文件的固定格式(/usr/include)
stdio.h 头文件
<> 从c语言的标准库查找头文件
"" 从指定目录下进行文件的查找如果查不到,我就去库函数中继续查找
int 函数的返回值类型
main 主函数 ,c语言程序有且只有一个主函数,是c程序的入口
int argc, const char *argv[] 是一个外部传参
{} 函数体,所有的代码都在里面写。
printf() 打印函数
"hello world" 字符串常量
\n 换行
; 分号c语言代码这一行的结束的标志,必须有,没有分号会 报错
// 单行注释
/* */ 多行注释 #if 0 # endif
return 退出函数
return 0 退出函数并且返回一个数据 0
return的作用:
1.函数的返回值
2.终止后续代码的执行
1.回答 吃 return sum
2.回答 我选亚索 return 1
3.不回答 return 终止后续代码的执行。
2.gcc 编译器
2.1直接编译
gcc 文件名 .c 会自动生成一个可执行文件(二进制文件、机器码)默认是a.out
运行程序 ./a.out
2.2分布编译 第一个面试题 40%~60%
ESc .iso
1.预处理
代码:gcc -E 文件名.c -o 文件名.i
作用:1.头文件的展开 2.宏的替换 3.删除注释(提高代码运行速度) 4.不会检查语法错误
2.编译
代码:gcc -S 文件名.i -o 文件名.s
作用:需要检查语法错误,会生成一个汇编文件
3.汇编
代码: gcc -c 文件名.s -o 文件名.o
作用:将汇编文件转换为二进制文件,但是没有链接到库,不可执行
4.链接库
代码:gcc 文件名.o -o 可执行文件
运行 ./可执行文件
3.宏定义
3.1无参宏定义
格式:
#define 宏名 宏体
示例:
#define N 2
3.2有参宏定义
格式:
#define 宏名(参数1,参数2) 宏体
示例:
#include <stdio.h>
#define N 2
#define ADD(a,b) a+b
int main(int argc, const char *argv[])
{
printf("hello\n");
printf("%d\n",N);
printf("%d\n",ADD(1,2));
return 0;
}
3.3注意事项
1.将宏定义放置在头文件之下
2.宏名必须大写(默认的潜规则---为了区分函数)
3.宏定义不需要加分号
4.宏就是一个【简单的替换】,如果传入的参数要优先运行,必须加上括号 #define SUB(a,b,c,d) a*(b + c)+d
5.面试题: 宏处在分布编译哪个阶段? 预处理阶段
6.宏体一定是一个表达式
3.4练习
#include <stdio.h>
#define M(x,y,z) x*y+z
int main(int argc, const char *argv[])
{
int a =1,b =2,c =3;
printf("%d\n",M(a+b,b+c,c+a));
return 0;
}
注意 简单的替换
计算步骤:
1+2*2+3+3+1 = 1+4+3+3+1 = 5+7 =12
一个水分子的质量是3.0*10(-23)g,1夸克脱水大约有950g,写一个程序
要求输入水的夸克数,计算这么多水中包含多少水分子?
科学计数法 3.0e-23 格式符:%e
n*950/(3.0e-23)
#include <stdio.h>
#define G 950
#define K 3.0e-23
#define S(a) (a)*G/(K)
int main(int argc, const char *argv[])
{
printf("%e\n",S(2));
return 0;
}
4.数据类型及变量
1.计算机的单位转换
1Tb = 1024Gb
1Gb = 1024Mb
1Mb = 1024Kb
1Kb = 1024byte
1byte(字节) = 8 bit(位)
1bit 只能存储一个 0或者一个 1
2.常量的数据类型
1.整形常量 %d
1 0 100 3
2.浮点型常量 %f
PI 3.1 9.8 -3.4 1.1.2.3(错误)
3.字符类型的常量----由单引号包含起来的单个字符 %c
'1' '-' '0' 'a'
ascii 国际通用的编码方式 man ascii
'0' ~ '9' 48~57 '0' 48
'A' ~'Z' 65~90 'A' 65
'a' ~'z' 97~122 'a' 97
'\n' 10 ?
4.字符串常量 由双引号包含起来的一个或多个字符。
"asdsafga" "a" "!@#$%%"
5.标识符类型的常量
#define N 1 # define STR "1234"
3.基本数据类型
1.整形
整形 | 所占内存空间的大小 | 格式符 |
---|---|---|
int | 4byte | %d |
short int | 2byte | %d |
long int | 64位操作系统下 8byte 32位操作系统下 4byte | %ld |
long long | 8byte | %ld |
2.浮点型
浮点型类型 | 所占空间的大小 | 格式符 |
---|---|---|
单精度浮点型 | 4byte | %f |
双精度浮点型 | 8byte | %lf |
3.字符型
数据类型 | 所占空间的大小 | 格式符 |
---|---|---|
char | 1byte | %c |
4.变量
4.1.申请变量
格式:
单个变量的声明 存储类型 数据类型 变量名(标识符)
多个变量的声明 存储类型 数据类型 变量名1,变量名2....
auto int a<----->int a
4.2.存储类型
auto 默认类型
extern 引用其他文件的变量
static 静态变量 (网络编程、IO)
底层课程
volatile 去内存中获取变量
register 寄存器变量
4.3.变量名
语义化命名
1.变量的初始化以及赋值
int a; a的值是一个随机值,但是
int b =1; 用常量进行初始化
int c = b; 用其他变量进行初始化
int d;//先定义一个变量整形变量b,所占空间大小为4byte
d = 4;//给这个变量d赋值常量4
2.标识符的命名规则
2.1不能以数字开头
2.2由字母、数字、下划线组成
2.3严格区分大小写
2.4不能以关键字重名
3.关键字
32个--由系统定义的语法,有特殊的含义
auto for if
extern long long short
static char
volatile double
register int
float
4.4.修饰的关键字
1.常用的修饰数据类型的关键字
有符号 signed
可以区分正负的,可以修饰 int char ,且是一个默认的类型
int a = -10; <----> signed int a =10;
char c = 10; 10 是字符所对应的ascii码值
无符号 unsigned
没有负数,只能为正数,可以修饰int char
unsigned int a =10;
unsigned int b =-10;//肯定是一个正数
4.5.取值范围
1.char
所占空间大小 1byte =8bit
unsigned char 最小值 0 最大值 2^8-1 [0,255]
signed char 符号位 0正数 1负数 [-128,127]
2.int
4.6.原、反、补
正数的原、反、补都是本身
原码:人脑能够识别出来的二进制形式
+0 = 0000 0000
-0 = 1000 0000
反码:
正数:反码就是原码本身
负数:符号位不变,其他位取反
+0 = 0000 0000
-0 = 1111 1111
补码:
正数:补码就是原码本身
负数:补码就是在反码的基础上,最后一位+1
+0 = 0000 0000
-0 = 1000 0000 原码 1111 1111 补码 1 1000 0000 补码 1000 0000 与-128的结果一样
4.7.占位符
%d 以有符号的十进制格式输出 int char
%ld 以有符号的十进制格式输出 long int
%nd n代表的是宽度,不够的补空格
%f 单精度浮点型输出
%lf 双精度输出
%.mf m代表的保留几位数字
%c 以字符形式输出
%s 以字符串输出
%p 以变量的地址形式输出
%e
%o 八进制
5、基本输入输出函数
5.1单个字符的输入与输出
1.输入
getchar()
功能:从终端输入单个字符
原型: int getchat(void);//void 代表为空
示例:
char c;
c = getchar();//假设我这里输入hello ,只能拿出第一个字符h
int d = getchar();
2.输出
putchar()
功能:从终端输出字符
原型: int putchar(int x)
示例:
putchar('a');//a
putchar('\n');//换行
putchar('c'); //c
putchar(10);//换行
putchar(97);//字符a
putchar(10);
5.2格式化输入与输出
1.输出
printf();
原型:int printf(const char *format,...)
示例:
printf("hello world %d %f",1,1.1);
注意:
1.1.双引号中填入要输出的数据,填什么输出什么,除了格式符和转义字符
1.2.占位符的个数,要去后面不定参数(...)个数一致,不定参数之间,需要用逗号隔开
2.格式化的输入
scanf();
功能:终端输入
原型:int scanf(const *format,...)
scanf("格式符,格式符",&(取地址符)变量名);
示例:
scanf("%d%d",&a,&b);
注意:
2.1 scanf()一次只能识别到空格,tab键,\n之前
2.2需要格式符和存储的数据类型保持一致
2.3把&加上
2.4 不要在scanf()写\n
2.5终端输入时一定要和scanf()里面的格式符的格式保持一致
5.4练习
用scanf先从终端获取一个int的数据类型,打印结果;
然后再用scanf从终端获取一个字符类型的变量,打印他们的结果
5.5吸收垃圾字符
getchar()
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a;
char c;
scanf("%d",&a);
printf("%d\n",a);
//getchar();//吃掉了垃圾字符,回车
scanf("%c",&c);
printf("%c\n",c);
return 0;
}
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a,b;
char c =10;
scanf("%d %d %c",&a,&b,&c);
printf("%d %d %c",a,b,c);
//getchar();//吃掉垃圾字符
scanf("%c",&c);
printf("%d %c\n",c,c);
return 0;
}
抑制字符 %*c
空格也可以吸收垃圾字符
char a,b,c,d;
scanf("%c",&a);
scanf(" %c",&a);
scanf(" %c",&a);
5.4转义字符
\n 换行
\t 水平制表符 tab键的大小
%% 打印%
\" 打印"
\\ 打印\
报错信息
bash: cd: 111: No such file(文件) or directory(目录)
bash: cd: root: Permission denied 访问被拒绝
mkdir: cannot create directory ‘day1’: File exists(存在)
rmdir: failed to remove 'day2': Directory not empty(空)
cp: -r not specified(规定、指定); omitting(省略) directory './day2'
1.c:6:2: error: expected(期望) ‘;’ before(在...之前) ‘return’
error: ‘k’ undeclared(未定义、未声明) (first use in this function(函数))
format ‘%c’ expects argument(参数) of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]