Linux系统作为学习C语言的开发环境
环境安装:
1、Ubuntu Linux.7z----------虚拟机系统
2、VMware:VMware Workstation 16 Pro 激活密钥.txt ; VMware-workstation-full-16.1.0-17198959.exe------虚拟机软件
3、安装VMware虚拟机.pdf----安装文档
1、安装虚拟机软件
2、在虚拟机软件中启用ubuntu系统
Ubuntu Linux.7z--解压
在vmware软件,打开虚拟机,选中
C语言环境:
ubuntu系统---->终端(terminal)
程序:解决完成特定功能(任务)的流程步骤
计算机程序:让计算机去实现解决问题的步骤执行
计算机语言:计算机能够识别任务的内容(指令)
机器语言:使用0和1表示指令功能
汇编语言(助记符语言):把机器指令用助记符进行表示
高级语言:类似自然语言的编写方式
C语言:高级语言,适合嵌入式开发
Linux中编写C语言程序
vim工具:在终端上编写文本文件内容----可以使用vim来写程序代码
vim:只是编辑器,类似于 windows 记事本,只负责写文本内容(程序内容)
vim终端的文本编辑器:创建、显示、编辑文本编辑器
vim操作:
vim:打开vim编辑
vim + xxxx文件名:使用vim 打开 xxxx文件
如果文件名不存在,创建一个新文件(临时)
vim操作文件,所有的操作都依靠键盘输入(键盘输入是:文本内容还是命令)
vim是多模式编辑器:
命令模式(默认):键盘输入(输入的任何内容),都是命令
插入模式:键盘输入,都是操作文本内容
底行模式:操作vim编辑器
插入命令
命令 |
作用 |
a |
在光标所在字符的位置之后插入 |
A |
在光标所在行的行尾插入 |
i |
在光标所在字符的位置之前插入 |
I |
在光标所在行的行首插入 |
o |
在光标所在行的下一行插入(新建行) |
O |
在光标所在行的上一行插入(新建行) |
定位命令
命令 |
作用 |
gg |
跳转到第一行的开头 |
GG 或 ]] |
跳转到最后一行的开头 |
nG |
跳转到第n行 |
:n |
跳转到第n行 |
0 |
跳转到光标所在行行首 |
$ |
跳转到光标所在行行尾 |
:set nu |
显示行号 |
:set nonu |
不显示行号 |
b |
跳转到前一个单词的第一个字符 |
w |
跳转到下一个单词的第一个字符 |
复制粘贴删除命令
命令 |
作用 |
yy |
复制光标当前行 |
nyy |
复制从光标开始的n行 |
p |
把复制或剪切的n行,粘贴到光标下一行(新建) |
dd |
剪切光标当前行 |
ndd |
剪切从光标开始的n行(删除,剪切不进行粘贴) |
x |
删除光标所在位置的字符 |
nx |
删除光标所在位置后n个字符 |
nX |
删除光标所在位置前n个字符 |
dG |
删除光标所在行开始到文件末尾 |
:n1,n2d |
从n1行开始删除到n2行结束 |
u |
恢复,撤销 |
保存退出命令
命令 |
作用 |
:w |
保存当前文件 |
:w 文件名 |
把当前文件额外保存一份为文件名,备份(另存为) |
:q |
退出当前文件 |
:q! |
强制退出 |
:x(!) |
(强制)保存且退出,x == wq |
:a |
所有文件 |
搜索替换命令
命令 |
作用 |
/查找内容 |
从当前光标位置开始查找对应内容,n:查找下一个,N:查找上一个 |
:%s/old/new |
全文替换指定字符串,%s:代表全文,把old 替换为 new |
:n1,n2s/old/new |
从n1行开始到n2行结束,把old替换为new |
r |
替换光标所在位置的字符,然后输入的字符就是替换的字符 |
R |
从当前光标开始,使用输入的内容替换当前行的内容 |
编译:把C程序翻译为计算机能够认识的指令(机器程序)
命令:gcc
gcc xxx文件名----->编译:进行对应的转换
生成一个编译好的(计算机能够识别,执行的程序):a.out
执行 可执行程序 :
./a.out
关键字:在规范C语言时,用于表示一定的特殊含义的字符,只要在C程序中使用,就代表了一定的操作和含义,约定的具有特定功能的单词或字符
int:整数类型
if:选择条件
for:循环
C语言程序中,我们所定义的名字不能和关键字重名(一样)
标识符:在当前程序中设定的一些字符符号表示,表示一定的意义,代表一个定义的作用(我们自己所定义的字符符号含义),自己命名的符号
标识符的表示:
由字母数字和下划线构成,且只能以 字母或 下划线开始
A-Z , a-z , 0-9 , _
合法标识符:
abc,a1,a2,o_k
非法标识符:
%abc,a$b,1a
在C语言程序中,数据值都有对应的数据类型
C语言是一种静态类型语言
基本类型:
1、整型
10、-10、1、-101
2、浮点型(实型)
1.2、3.1415、-1.2
3、字符型
'a'、'#'、'0'
对于计算机而言,只认识 0 和 1
十进制表示:每位数据值范围:0、1、2、3、4、5、6、7、8、9
满10进1
120
二进制表示:每位数据值范围:0、1,计算机中存储数据以二进制存储
满2进1
0b110
八进制表示:每位数据值范围:0、1、2、3、4、5、6、7
满8进1
0110
十六进制表示:每位数据值范围:0、1、2、3、4、5、6、7、8、9、A(10)、B(11)、C(12)、D(13)、E(14)、F(15)
满16进1
0x110
整数十进制转二进制:除以2取余数,把余数按照从低位到高位依次表示
15
/ 2-------------1
7
/ 2-------------1
3
/ 2-------------1
1
/ 2-------------1
0
15-------->(0000.....000) 1111
小数十进制转二进制:乘以2 取整 取到规定的位数
0.2====>
0.2
2
0.4-----------0
2
0.8-----------0
2
0.6-----------1
2
0.2-----------1
== 0011 0011 0011 ......
= 0011 0011 00
0.25====>
0.25
2
0.5-----------0
2
0.0-----------1
== 01
二进制转十进制:二进制每一位的权 乘以 当前位的值 (权:以2为底数,以位数为指数幂)的累加和
10101 ====>
1 * 2^0 + 0 * 2^1 + 1 * 2^2 + 0 * 2^3 + 1 * 2^4
= 1* 1 + 1 * 4 + 1 * 16 = 1 + 4 + 16 = 21
十六进制转十进制:十六进制每一位的权 乘以 当前位的值 (权:以16为底数,以位数为指数幂)的累加和
7A======>
A * 16^0 + 7 * 16^1 = 10 + 112 = 122
十进制转十六进制:除以16取余数,把余数按照从低位到高位依次表示
234
/ 16---------10(A)
14
/ 16--------14(E)
0
234=====>EA
二进制转十六进制/八进制:把四位/三位 二进制转为一个十六进制位/八进制位,如果高位不够补0进行转换
10101010111====>16进制
0 101 0101 0111===> 5 5 7
10101010111====>8进制
010 101 010 111====>2 5 2 7
十六进制/八进制转二进制:
计算机以二进制方式(0、1)存储数据,但是数据中存在 正 负之分
有符号数:把数据中,最高位作为符号位,用0表示正数,用1表示负数
无符号数:数据中,所有位都是数据位,没有符号位,所有无符号数都是正数
计算机中存储数据是以 补码 格式存储
原码:数据的二进制格式
10:0 .....0000... 1010
-10:1 .....0000... 1010
反码:
正数:反码 == 原码
负数:在原码的基础上每一位(除了符号位)取反(1变为0,0变为1)
10:0 .....0000... 1010
-10:1 .....1111... 0101
补码:
正数:补码 == 原码
负数:在反码的基础上 + 1
10:0 .....0000... 1010
-10:1 .....1111... 0110
位:bit
一个单独的0或1 二进制----1bit
字节:byte
八位二进制---------1Byte 1B = 8bit
千字节:KByte---KB
一千个字节---------1KB 1KB = 1000B
整数存储
二进制,补码形式存储
整型:根据在计算机中设定的大小
short (int):短整型------16位二进制(16bit),2B
int:整型-------------32位(32bit),4B
long (int):长整型-------在32位系统大小为 32位(32bit),4B ;在64位系统大小为 64位(64bit),8B
long long (int):超长整型----64位(64bit),8B
有符号数:
(signed):有符号数,最高位为 符号位
无符号数:
unsigned:无符号数,没有符号位
32位无符号整数:unsigned int
16位有符号整数:signed short int--------->short
浮点型存储:
二进制,补码形式存储
数据部分 + 指数部分
浮点型:设定类型大小
float:单精度浮点型---32位(32bit),4B,精度:6/7
符号位:1bit
阶码:8bit
尾数:23bit
double:双精度浮点型-----64位(64bit),8B,精度:15/16
符号位:1bit
阶码:11bit
尾数:52bit
定义 一个32位浮点数:float
对于字符型数据,在计算机中存储,依旧使用二进制 0 和 1表示
对于每个字符统一用一种标准的二进制来表示
在C语言中,使用 ASCII码来表示(小整数)
ASCII码表
Bin (二进制) |
Oct (八进制) |
Dec (十进制) |
Hex (十六进制) |
缩写/字符 |
解释 |
0000 0000 |
00 |
0 |
0x00 |
NUL(null) |
空字符 |
0000 0001 |
01 |
1 |
0x01 |
SOH(start of headline) |
标题开始 |
0000 0010 |
02 |
2 |
0x02 |
STX (start of text) |
正文开始 |
0000 0011 |
03 |
3 |
0x03 |
ETX (end of text) |
正文结束 |
0000 0100 |
04 |
4 |
0x04 |
EOT (end of transmission) |
传输结束 |
0000 0101 |
05 |
5 |
0x05 |
ENQ (enquiry) |
请求 |
0000 0110 |
06 |
6 |
0x06 |
ACK (acknowledge) |
收到通知 |
0000 0111 |
07 |
7 |
0x07 |
BEL (bell) |
响铃 |
0000 1000 |
010 |
8 |
0x08 |
BS (backspace) |
退格 |
0000 1001 |
011 |
9 |
0x09 |
HT (horizontal tab) |
水平制表符 |
0000 1010 |
012 |
10 |
0x0A |
LF (NL line feed, new line) |
换行键 |
0000 1011 |
013 |
11 |
0x0B |
VT (vertical tab) |
垂直制表符 |
0000 1100 |
014 |
12 |
0x0C |
FF (NP form feed, new page) |
换页键 |
0000 1101 |
015 |
13 |
0x0D |
CR (carriage return) |
回车键 |
0000 1110 |
016 |
14 |
0x0E |
SO (shift out) |
不用切换 |
0000 1111 |
017 |
15 |
0x0F |
SI (shift in) |
启用切换 |
0001 0000 |
020 |
16 |
0x10 |
DLE (data link escape) |
数据链路转义 |
0001 0001 |
021 |
17 |
0x11 |
DC1 (device control 1) |
设备控制1 |
0001 0010 |
022 |
18 |
0x12 |
DC2 (device control 2) |
设备控制2 |
0001 0011 |
023 |
19 |
0x13 |
DC3 (device control 3) |
设备控制3 |
0001 0100 |
024 |
20 |
0x14 |
DC4 (device control 4) |
设备控制4 |
0001 0101 |
025 |
21 |
0x15 |
NAK (negative acknowledge) |
拒绝接收 |
0001 0110 |
026 |
22 |
0x16 |
SYN (synchronous idle) |
同步空闲 |
0001 0111 |
027 |
23 |
0x17 |
ETB (end of trans. block) |
结束传输块 |
0001 1000 |
030 |
24 |
0x18 |
CAN (cancel) |
取消 |
0001 1001 |
031 |
25 |
0x19 |
EM (end of medium) |
媒介结束 |
0001 1010 |
032 |
26 |
0x1A |
SUB (substitute) |
代替 |
0001 1011 |
033 |
27 |
0x1B |
ESC (escape) |
换码(溢出) |
0001 1100 |
034 |
28 |
0x1C |
FS (file separator) |
文件分隔符 |
0001 1101 |
035 |
29 |
0x1D |
GS (group separator) |
分组符 |
0001 1110 |
036 |
30 |
0x1E |
RS (record separator) |
记录分隔符 |
0001 1111 |
037 |
31 |
0x1F |
US (unit separator) |
单元分隔符 |
0010 0000 |
040 |
32 |
0x20 |
(space) |
空格 |
0010 0001 |
041 |
33 |
0x21 |
! |
叹号 |
0010 0010 |
042 |
34 |
0x22 |
" |
双引号 |
0010 0011 |
043 |
35 |
0x23 |
# |
井号 |
0010 0100 |
044 |
36 |
0x24 |
$ |
美元符 |
0010 0101 |
045 |
37 |
0x25 |
% |
百分号 |
0010 0110 |
046 |
38 |
0x26 |
& |
和号 |
0010 0111 |
047 |
39 |
0x27 |
' |
闭单引号 |
0010 1000 |
050 |
40 |
0x28 |
( |
开括号 |
0010 1001 |
051 |
41 |
0x29 |
) |
闭括号 |
0010 1010 |
052 |
42 |
0x2A |
* |
星号 |
0010 1011 |
053 |
43 |
0x2B |
+ |
加号 |
0010 1100 |
054 |
44 |
0x2C |
, |
逗号 |
0010 1101 |
055 |
45 |
0x2D |
- |
减号/破折号 |
0010 1110 |
056 |
46 |
0x2E |
. |
句号 |
0010 1111 |
057 |
47 |
0x2F |
/ |
斜杠 |
0011 0000 |
060 |
48 |
0x30 |
0 |
字符0 |
0011 0001 |
061 |
49 |
0x31 |
1 |
字符1 |
0011 0010 |
062 |
50 |
0x32 |
2 |
字符2 |
0011 0011 |
063 |
51 |
0x33 |
3 |
字符3 |
0011 0100 |
064 |
52 |
0x34 |
4 |
字符4 |
0011 0101 |
065 |
53 |
0x35 |
5 |
字符5 |
0011 0110 |
066 |
54 |
0x36 |
6 |
字符6 |
0011 0111 |
067 |
55 |
0x37 |
7 |
字符7 |
0011 1000 |
070 |
56 |
0x38 |
8 |
字符8 |
0011 1001 |
071 |
57 |
0x39 |
9 |
字符9 |
0011 1010 |
072 |
58 |
0x3A |
: |
冒号 |
0011 1011 |
073 |
59 |
0x3B |
; |
分号 |
0011 1100 |
074 |
60 |
0x3C |
< |
小于 |
0011 1101 |
075 |
61 |
0x3D |
= |
等号 |
0011 1110 |
076 |
62 |
0x3E |
> |
大于 |
0011 1111 |
077 |
63 |
0x3F |
? |
问号 |
0100 0000 |
0100 |
64 |
0x40 |
@ |
电子邮件符号 |
0100 0001 |
0101 |
65 |
0x41 |
A |
大写字母A |
0100 0010 |
0102 |
66 |
0x42 |
B |
大写字母B |
0100 0011 |
0103 |
67 |
0x43 |
C |
大写字母C |
0100 0100 |
0104 |
68 |
0x44 |
D |
大写字母D |
0100 0101 |
0105 |
69 |
0x45 |
E |
大写字母E |
0100 0110 |
0106 |
70 |
0x46 |
F |
大写字母F |
0100 0111 |
0107 |
71 |
0x47 |
G |
大写字母G |
0100 1000 |
0110 |
72 |
0x48 |
H |
大写字母H |
0100 1001 |
0111 |
73 |
0x49 |
I |
大写字母I |
01001010 |
0112 |
74 |
0x4A |
J |
大写字母J |
0100 1011 |
0113 |
75 |
0x4B |
K |
大写字母K |
0100 1100 |
0114 |
76 |
0x4C |
L |
大写字母L |
0100 1101 |
0115 |
77 |
0x4D |
M |
大写字母M |
0100 1110 |
0116 |
78 |
0x4E |
N |
大写字母N |
0100 1111 |
0117 |
79 |
0x4F |
O |
大写字母O |
0101 0000 |
0120 |
80 |
0x50 |
P |
大写字母P |
0101 0001 |
0121 |
81 |
0x51 |
Q |
大写字母Q |
0101 0010 |
0122 |
82 |
0x52 |
R |
大写字母R |
0101 0011 |
0123 |
83 |
0x53 |
S |
大写字母S |
0101 0100 |
0124 |
84 |
0x54 |
T |
大写字母T |
0101 0101 |
0125 |
85 |
0x55 |
U |
大写字母U |
0101 0110 |
0126 |
86 |
0x56 |
V |
大写字母V |
0101 0111 |
0127 |
87 |
0x57 |
W |
大写字母W |
0101 1000 |
0130 |
88 |
0x58 |
X |
大写字母X |
0101 1001 |
0131 |
89 |
0x59 |
Y |
大写字母Y |
0101 1010 |
0132 |
90 |
0x5A |
Z |
大写字母Z |
0101 1011 |
0133 |
91 |
0x5B |
[ |
开方括号 |
0101 1100 |
0134 |
92 |
0x5C |
\ |
反斜杠 |
0101 1101 |
0135 |
93 |
0x5D |
] |
闭方括号 |
0101 1110 |
0136 |
94 |
0x5E |
^ |
脱字符 |
0101 1111 |
0137 |
95 |
0x5F |
_ |
下划线 |
0110 0000 |
0140 |
96 |
0x60 |
` |
开单引号 |
0110 0001 |
0141 |
97 |
0x61 |
a |
小写字母a |
0110 0010 |
0142 |
98 |
0x62 |
b |
小写字母b |
0110 0011 |
0143 |
99 |
0x63 |
c |
小写字母c |
0110 0100 |
0144 |
100 |
0x64 |
d |
小写字母d |
0110 0101 |
0145 |
101 |
0x65 |
e |
小写字母e |
0110 0110 |
0146 |
102 |
0x66 |
f |
小写字母f |
0110 0111 |
0147 |
103 |
0x67 |
g |
小写字母g |
0110 1000 |
0150 |
104 |
0x68 |
h |
小写字母h |
0110 1001 |
0151 |
105 |
0x69 |
i |
小写字母i |
0110 1010 |
0152 |
106 |
0x6A |
j |
小写字母j |
0110 1011 |
0153 |
107 |
0x6B |
k |
小写字母k |
0110 1100 |
0154 |
108 |
0x6C |
l |
小写字母l |
0110 1101 |
0155 |
109 |
0x6D |
m |
小写字母m |
0110 1110 |
0156 |
110 |
0x6E |
n |
小写字母n |
0110 1111 |
0157 |
111 |
0x6F |
o |
小写字母o |
0111 0000 |
0160 |
112 |
0x70 |
p |
小写字母p |
0111 0001 |
0161 |
113 |
0x71 |
q |
小写字母q |
0111 0010 |
0162 |
114 |
0x72 |
r |
小写字母r |
0111 0011 |
0163 |
115 |
0x73 |
s |
小写字母s |
0111 0100 |
0164 |
116 |
0x74 |
t |
小写字母t |
0111 0101 |
0165 |
117 |
0x75 |
u |
小写字母u |
0111 0110 |
0166 |
118 |
0x76 |
v |
小写字母v |
0111 0111 |
0167 |
119 |
0x77 |
w |
小写字母w |
0111 1000 |
0170 |
120 |
0x78 |
x |
小写字母x |
0111 1001 |
0171 |
121 |
0x79 |
y |
小写字母y |
0111 1010 |
0172 |
122 |
0x7A |
z |
小写字母z |
0111 1011 |
0173 |
123 |
0x7B |
{ |
开花括号 |
0111 1100 |
0174 |
124 |
0x7C |
| |
垂线 |
0111 1101 |
0175 |
125 |
0x7D |
} |
闭花括号 |
0111 1110 |
0176 |
126 |
0x7E |
~ |
波浪号 |
0111 1111 |
0177 |
127 |
0x7F |
DEL (delete) |
删除 |
字符存储:
存储的字符对应的ASCII码,ASCII码就是整数,以二进制存储
字符类型:
char:字符类型--------8位(8bit),1B
字符类型可以当做整数进行操作:char 可以表示为 只有8位的整数
常量:在整个程序中都不会进行改变的数据
变量:在整个程序中可以进行变化的数据,在内存中存储数据后,空间中的数据值可以进行改变,变量在使用的使用需要有一个名字(能够找到对应的变量);变量是什么类型
对于变量而言,必须先有(定义),才能使用
变量定义:
存储类型 数据类型 变量名;
变量名:使用标识符来表示(相当于赋予了变量数据的含义)
存储类型:
auto:默认类型
通常可以省略,表示定义在栈区,由系统进行管理
static:静态类型
register:寄存器类型,存储到cpu中(通常等同于 auto)
extern:外部类型
变量初始化:
在定义变量时,为变量赋初始值
存储类型 数据类型 变量名 = 值;
printf:由C语言标准所设计的输出功能,只要使用printf就可以实现输出打印(终端)
printf功能包含在 stdio.h中
所以要使用的话:#include
格式:
printf("要输出打印的内容 格式化字符1,格式化字符2 ", 输出列表);
格式化字符:作用就是占位 表示要打印对应的数据值,以% 表示
输出列表:格式化字符要打印的数据
格式化字符:%
格式字符 |
功能说明 |
d 或 i |
以带符号的十进制形式输出整数(正数不显示+),i 是老式写法,现多用 d |
u |
以无符号的十进制形式输出整数 |
hd 或 ld 或 lld |
分别以短整型 short、长整型 long、超长整型 long long 输出 |
o |
以八进制无符号形式输出整数 |
X 或 x |
以十六进制无符号形式输出整数,x 表示十六进制的a~f小写,X 则 A~F大写 |
f |
以定点十进制小数形式输出浮点数 |
E 或 e |
以指数形式输出十进制浮点数,e 表示 e 小写,E 表示 E 大写 |
G 或 g |
根据数值自动采用 f 或 e 方式输出,区别在于会自动省去尾随的 0 或小数点 默认精度为 6 |
c |
以字符形式输出,只输出一个字符 |
s |
以字符串形式输出 |
p |
输出指针的值或变量的地址值 |
格式化字符输出指定的位数:
%m.p格式字符:m 数据的宽度,p小数的精度
在输出中,如果要输出某些特殊字符,在字符编码上没有对应的字符表示,在C语言中,设计转义字符:把普通字符转义为特殊字符,特殊字符转义为普通字符
转义字符: \
回车换行:\n
反斜线字符:\\
\:续行符
字符 |
功能说明 |
ASCII |
\a |
响铃(BEL) |
007 |
\b |
退格(BS) ,将当前位置移到前一列 |
008 |
\f |
换页(FF),将当前位置移到下页开头 |
012 |
\n |
换行(LF) ,将当前位置移到下一行开头 |
010 |
\r |
回车(CR) ,将当前位置移到本行开头 |
013 |
\t |
水平制表(HT) (跳到下一个TAB位置) |
009 |
\v |
垂直制表(VT) |
011 |
字符 |
功能说明 |
ASCII |
\\ |
代表一个反斜线字符''\' |
011 |
\’ |
代表一个单引号(撇号)字符 |
092 |
\” |
代表一个双引号字符 |
039 |
\? |
代表一个问号 |
034 |
\0 |
空字符(NUL) |
0 |
\ddd |
1到3位八进制数所代表的任意字符 |
000 |
\xhh |
十六进制所代表的任意字符 |
三位八进制 |
scanf:输入功能,可以从键盘输入数据给变量
使用scanf 必须包含对应的头文件 #include
格式:
scanf("键盘输入匹配,格式化字符1,格式化字符2,",输入列表);
格式化字符:格式化字符位置匹配的内容输入到变量中
输入列表:列出要输入的变量
注意:如果是连续两个数值格式化字符,在键盘输入时需要隔开(空格、回车)
只要是使用运算符进行运算,都会有结果,且结果就在运算的位置
+:加法
-:减法
*:乘法
/:除法
%:取余数(整数运算)
进行运算时,如果是同种类型数据进行运算,则结果为对应的类型
隐式类型转换:
在进行各种运算操作,如果是不同的数据类型,会把不同的数据类型转换为相同的数据类型然后再进行运算(原则:精度低往精度高的类型转换),原数据不变
强制类型转换:
把数据的值取出,然后指定转换为某种类型,原数据不变
语法格式:
(要转换的类型)数据
< 小于
<= 小于等于
> 大于
>= 大于等于
== 等于
!= 不等于
关系运算符是进行比较运算,判断关系是否成立(比较左右两边的表达式是否满足关系),比较结果:成立为真(值:1),不成立为假(值:0)
注意:在进行运算时,如果有连续的多个运算符,单一运算符进行运算之后得到结果再与下一个运算符进行运算
注意:
浮点数a 和 b 判断相等
a - b > -精度 && a - b < 精度
连接表达式,根据表达式的真 假,进行组合得到新的结果,结果也是 真(值:1) 假(值:0)
逻辑运算表示两个数据或表达式之间的逻辑关系,逻辑运算的结果也只有两个:真为1和假为0。
&& (与):
表达式1 && 表达式2
如果表达式1为真,且表达式2为真,逻辑与 结果 为真(值:1),否则 逻辑与 结果为假(只要有一个表达式为假,结果为假)(值:0)------判断,表达式1 和表达式2 是否同时成立为真
截断原则:当表达式1 已经为 假(0),不会运算 表达式2
|| (或):
表达式1 || 表达式2
如果表达式1和表达式2 都为 假,逻辑或 结果为 假(值:0),否则 逻辑或为真(只有有一个表达式为真,结果为真)(值:1)-----判断,表达式1和表达式2 是否同时都不成立为假(是否存在表达式为真)
截断原则:当表达式1 已经为 真(1),不会运算 表达式2
! (非):
!表达式
改变表达式的真假结果,如表达式为假,逻辑非 结果为 真(值:1),如表达式为真,逻辑非 结果为 假(值:0)
位运算对数据中的对应的二进制位进行运算操作(不会涉及到符号位说法)
&(位与)
表达式/数1 & 表达式/数2
把数1的二进制 与 数2的二进制,对应的每一位进行与运算操作(两个数对应的位有0,为0,都为1,则为1,位运算规则为:1 & 1 = 1 0 & 1 = 0 1 & 0 = 0 0 & 0 = 0)
|(位或)
表达式/数1 | 表达式/数2
将两个运算量的各个相应位分别进行“或”运算操作(两个数对应的位,有1,为1,都为0,则为0,运算规则为:1 | 1 = 1 0 | 1 = 1 1 | 0 = 1 0 | 0 = 0)
^(位异或)
表达式/数1 ^ 表达式/数2
将两个运算量的各个相应位分别进行“异或”运算(两个数对应的位,相同为0,不同为1,运算规则为:1 ^ 1 = 0 0 ^ 1 = 1 1 ^ 0 = 1 0 ^ 0 = 0)
~(位取反)
~数
将一个数据中所有位都取其相反值,即1变0,0变1,运算规则为: ~1 --> 0 ~0 --> 1
<<(按位左移)
数据值 << 移动位数
将一个数据所有二进制位向左移若干位,左边(高位)移出的部分舍去,右边(低位)自动补零
>>(按位右移)
数据值 << 移动位数
将一个数据所有二进制位向右移若干位,右边(低位)移除的部分舍去,左边(高位)根据原最高位自动补值(原最高位为1:补1,元最高位为0,补0)
复合运算符:可以使用 = (赋值运算符)和 其他的运算符(算数运算符,位运算符)结合使用
+=、-=、*=、/=、%=、|= 、&=、^=
变量 += 表达式======> 变量 = 变量 + (表达式)
++ 、 --
变量++:先取变量的值,进行其他运算,然后变量 +1 ,使用变量时,使用+1之前的值
变量;
变量 += 1;
++变量:先把变量+1,然后取变量的值,进行其他运算
变量 += 1;
变量;
变量--
--变量
前缀:先自增自减后再参与表达式运算。
后缀:先参与表达式运算,后自增自减。
运算符---- ? :
条件表达式:
表达式1 ? 表达式2 : 表达式3
表达式1为真,执行表达式2,把表达式2的结果作为整个条件表达式的结果
为假,执行表达式3,把表达式3的结果作为整个表达式的结果
逗号运算符
表达式1,表达式2,…,表达式n
依次运算操作每个表达式,把最后一个表达式运算作为整个逗号运算符的结果
sizeof(数值/类型):作用 计算数据 对应类型的大小,以字节表示
sizeof 运算符,计算类型、变量或表达式的空间大小(字节数)
sizeof(变量);
sizeof(表达式);
sizeof(类型);
作业:
(1)输入两个数求和
(2)提取电话号码 在下列输入字符串中豪华单间出租,联系电话:13888888888
(3)求下列表达式的值 int x=1,y=2,z=5;
x>0 && !(y==3) || z>5 --> 1&&!(y==3)|| z>5 --> 1&& 1|| z>5 -->1|| z>5 -->1
!(x+1>0) && y==0 ||z>0 --> !(1) && y==0|| z>0 -->0&& y==0 || z>0 --> 0 || z>0 --> 0||1-->1
x<0 || y==0 && z>0 -->0|| y==0 && z>0 --> 0&& z>0 -->0 &&0 -->0
x=y>z ? z>0? 5: y: 10; -->x=0 ? z>0? 5: y: 10; --> x=0? 1?5:y :10; --> x=0? 5 :10;--> x=10 // 运算嵌套采用就近原则
(4)使用三目运算符,求x,y,z中的最大值
思考:
(1)输入一个整数,输出其二进制
(2)输入一个数,分解质因数
(3)输入一个数,判断是否为质数 只能被1和它本身整除的数
(5)使用三目运算符,判断输入的年是否为闰年
根据实际的当前情况条件,选择性执行/选择性不执行某些功能内容
根据条件,如果满足条件 则 执行对应的功能操作代码,执行完后,然后继续往下执行;否则跳过对应的功能代码,继续往下执行
if(条件表达式)
{
语句块;
}-----{}满足if选择的范围语句块,如果语句块只有 一条 语句,则{}可省略
条件表达式:只计算表达式的结果为 真(非0) 或 假(0)
如果满足条件则执行语句块,否则跳过语句块
满足条件表达式,执行一段语句功能内容,不满足则执行另一段功能内容;之后继续往下执行
if(表达式)
语句块1;
else
语句块2;
如果满足表达式,则执行语句块1,否则执行else 语句块2
if(表达式1)
语句块1;
else if(表达式2)
语句块2;
else if(表达式3)
语句块3;
……
[else
语句块n;]
多种情况选择性执行一种,判断第一种是否满足,满足则执行,不满足则判断下一种是否满足,满足则执行,不满足则继续判断.....
注意:if选择,只看真假,经过各种运算得到 0 或者 非0 都可以
switch选择结构,根据表达式的结果表示从多种情况进行选择,选择情况(表达式 == 情况)进行执行对应的语句块
switch (表达式)
{
case 常量表达式1:语句块1;break;//每个case 就是一个情况
case 常量表达式2:语句块2;break;
case 常量表达式n:语句块n;break;
default: 默认情况语句段n+1;[break];
}
注意:表达式和常量表达式 结果为 整型(因为要判断相等)
比较 switch 表达式 是否 等于 case 常量表达式 ,如果相等 则执行对应的语句块
default 表示 如果 switch 和case 比较所有都不相等,则执行default 默认语句块
当switch 表达式和 case 表达式 比较相等后则执行对应的语句块,同时所有的case 表达式都失效(则会从当前case 一直往后执行,直到swicth结束)
break:表示结束当前switch
重复多次执行某个功能
表达式为真,则执行一次要重复的内容(循环体语句),再次判断表达式是否真,表达式位置,则再次执行一次要重复的内容,继续判断表达式,直到表达式为假,则跳出循环执行while的后面内容
while (表达式)-------条件,是否重复执行
{
循环体语句;------要重复执行的内容
}
表达式的初始条件值
条件表达式
循环中包含改变条件值
作业:
1、企业根据营业额发奖金,低于10万,按0.1%发放,高于10万低于20万,10万按0.1%发放,高于10万间按0.2%发放;高于20万低于30万,10万按0.1%发放,10-20万按0.2%发放,高于20万部分按0.3%;高于30万,按0.4%发放,请输入金额,计算发放奖金
2、一个整数,它加上100是完全平方数,在加上100的基础上再加上168又是另一个完全平方数,求这个数
3、统计所有的水仙花数
4、有一对兔子,从第三个月开始每一个月都会生下一对兔子,小兔子经过三个月,每个月也能生下一对兔子,如果兔子不死,则,每个月有多少对兔子(只用输出前40个月,第一个月1对,第二个月1对)
5、猴子第一天摘了n个桃子,第一天吃了一半+1个,第二天又吃了剩下的桃子的一半+1,之后每天都是吃了前一天剩下的一半+1,第9天吃了后只剩下1个,问第一天摘了多少
do...while循环:先直接执行一次循环体,条件表达式从第二次开始判断是否满足,执行
语法结构:
do
{
循环体语句;
}
while (表达式);
while与do...while 区别:while从第一次条件开始判断,do...while 跳过第一次条件判断,从第二次判断开始;do...while最少执行一次
语法格式:
for (表达式1;表达式2;表达式3)
{
循环体语句;
}
表达式1:在整个for循环之前执行一次,且只执行一次,通常用于在for循环初始化条件的值(可以不进行设置,相当于没有初始化,可能在其他之前位置设置)
表达式2:循环条件,每次执行循环体前,先判断条件是否成立(判断一次,执行一次循环体)(可以不设置,相当于 条件一直为真 1)
表达式3:每次在执行一次循环体后,就立即执行(先于下次的条件判断),通常用于设置改变条件(可以不设置,相当于在表达式3中无操作)
表达式可以省略,但是 ; 必须添加
在循环内部循环体语句可能包含另一个循环,叫做循环的嵌套
while()
{
循环体
for()
{
}
}
外层循环执行一次,内层循环执行完一遍
break:break语句作用是结束当前这个循环,跳出当前循环
while()
{
break;-------从当前位置结束整个循环
}
continue:提前结束循环中的本次循环,跳过本次循环体没有执行完的内容,直接进行下一次
while循环使用continue直接结束本次循环体内容,直接进行下一次条件判断
for循环使用continue直接结束本次循环体内容,但是由于for循环在结束一次循环后,会执行表达式3,所以continue结束时,跳到表达式3执行,进行下一次条件判断
作业:
1、一辆汽车以平均80公里的时速行驶了4个小时。编写并运行一个C语言程序,显示这辆汽车已行驶的距离(公里),每半小时一次,直到旅程结束。
2、输入 年月日:如2021-7-5 ,计算当前日期是这一年的第几天
3、打印9 * 9 乘法表
函数:代码或代码块的集合,或特定功能代码的集合,把实现某种功能的代码单独实现形成一个整体,可以进行单独使用。就是一个独立的功能代码模块,在需要使用这个功能时,进行调用,就会去执行这个功能模块
库函数:由C语言标准实现的功能模块函数,编译器自带已经实现的函数
自定义函数:在程序中由于可能多次使用某个功能,自己实现这个功能模块函数,由用户对其进行定义,在其函数的定义中完成函数特定的功能,这样才能被其他函数调用
函数:包含两部分---函数头与函数体
函数头:
对函数的描述说明,表示某个函数----标记
3个部分:
返回值类型:函数功能结束,返回的结果是什么类型,表示有一个结果返回
函数名:标识符,表示这个功能的名字,之后就使用这个名字来标识使用这个功能函数
参数列表:在编写功能时不确定,需要在调用使用这个函数,传递的值
函数体:
功能模块的操作代码--功能的实现
定义:
返回值类型 函数名(参数列表)
{
函数体——函数实现特定功能的过程;
}
void:空类型,没有数据类型
void 不能定义变量
void 函数名()
{
函数体;
[return;]
}
没有返回值可以使用void修饰返回值类型
返回值数据类型 函数名()
{
函数体;
return 表达式值;
}
有返回值在定义函数时就要给定返回值类型 如int float char
return:只要执行到return 语句,表示 函数功能到这里结束
return + 值:结束当前函数,同时把 值 返回,返回到调用位置(在调用位置得到函数的执行结果)
对于有返回值类型,在函数体中 必须包含 return + 值 语句
void 函数名(参数列表):使用参数列表作为函数功能的输入,在编写函数功能时,存在不确定的一些数据值,使用参数列表来表示在定义函数功能时不确定;在使用时,根据参数列表情况,调用时传递参数列表实际的值
{
函数体;
}
参数列表格式:
数据类型1 变量名1,数据类型 变量名2,......
返回值类型 函数名(参数类型1 参数名1,参数类型2 参数名2,...)
{
函数体;
return 值;
}
在需要的位置使用这个函数功能,叫做函数调用,即:运行一次这段代码块
调用过程:
当调用时,跳转到对应函数位置进行执行函数功能,当函数执行完({}结束或return语句), 再跳转回调用位置,继续执行
函数名()
调用无参函数,则没有参数列表,但小括号不能省略
函数名()
调用有返回值函数,在调用位置就会得到函数返回结果
函数名(参数的值1,参数值2,参数值3,......)
在调用时,参数值 需要和 函数定义的参数列表 一一对应
在调用时,会把参数值 赋值(传递)给 参数列表中的变量
注意:调用时,参数值 可能是变量,表示把变量的值传递给函数的参数列表,而不是把变量直接传递给参数列表
函数名(参数值1,参数值2,参数值3,.....)
调用有返回值函数,在调用位置就会得到函数返回结果
定义有参函数时,给定的参数列表,在参数列表中的参数,叫做 形式参数(形参)
调用有参函数时,给定的参数值,叫做实际参数(实参)
在调用一个函数的过程中,被调用的函数又可以调用另一个函数
函数的定义是平行的、独立的,不允许嵌套定义
编译时提示函数是什么样子的函数(有无函数,函数有无返回值,有无形式参数列表)
如果在前面调用了函数,在后面位置才进行定义需要在调用前进行声明
函数声明 语法:
返回类型 函数名(形式参数列表);
写法:
返回类型 函数名(参数类型1,参数类型2,参数类型3....);
返回类型 函数名(参数类型1 参数名1,参数类型2 参数名2,参数类型3 参数名3....);
函数中直接或间接调用自己这个函数,叫做函数的递归调用,当前函数也叫做递归函数
通常递归函数需要用结束条件,在函数内部加控制语句,只有当满足一定条件时,递归终止
只要在函数内部定义的变量就叫做局部变量
函数的形式参数类似局部变量 ,与局部变量有相同的性质
性质:
生命周期:存储期限。变量的存储期限,在变量所在程序区块执行期间有效存储,区间结束或函数返回时,局部变量的值无法保留。
作用域:局部变量在定义所在的区域块内访问可达,离开区块不可访问。
程序块:用一对大括号{}括起来多条语句区域就是一个程序区块
不在函数内定义的变量叫做全局变量
性质:
生命周期:存储期限。变量的存储期限,在整个程序运行期间都存在有效。
作用域:从变量被定义的点开始一直到所在文件的末尾都可以使用访问。
在程序中,如果作用域相同则变量不能相同
在不同作用域时,允许定义相同的变量名,如果存在相同的变量则默认使用作用域小的变量进行操作
当变量定义时,如果没有进行初始化时,变量的默认值:
局部变量:随机值
全局变量:默认初始化为0
static静态存储类型
static修饰局部变量:
延长生命周期为整个程序(程序结束变量的生命周期结束),但是作用域不变,只能在定义变量的作用域中使用(但作用域仍为局部)
当多次定义static 的局部变量时,只会定义第一次,之后都是跳过定义
static修饰全局变量:
设置为静态变量,只能在本文件内使用这个变量
static修饰的变量未初始化会自动初始化为0
练习:实现一个函数,计算指定范围内的质数
作业:
1、编写一个函数,输入多个字符,分别统计字母、空格、数字和其他字符的个数,打印分别的统计值
2、输入一个五位数,判断是否为回文数
3、实现函数输入x,y 打印 x和y 的公约数(公约数:就是都能整除的数,如 x = 9,y = 12,公约数为 3)
数组:由多个数据组成一个数据集合,在集合中存在多个数据内容,数组是包含有多个数据值的数据结构,并且每个数据值具有相同的数据类型
数组元素:数组这个集合中的一个数据
定义:
类型 数组名[数组长度];
类型:每个数据的类型
数组名:整个数据集合的名字
数组长度:数据集合中数据的个数
如:
int a[4];
占用内存空间:类型 * 数组长度
以连续的内存空间创建数组,每个数组元素是相邻的
存取特定的数组元素,通过数组名在后边加上一个用方括号表示整数值(整数值:数组取下标、索引:从0开始的编号位置)
格式:
数组名[下标]
下标:下标值只能是整数或结果为整数的表达式,取值范围是 0 ~ 数组长度 - 1
注意:如果下标 >= 数组长度 叫做越界,不能使用
在定义一维数组时,可以对数组进行初始化,对数组进行初始化就是对数组的元素进行初始化
使用一个 {},在 花括号中,添加要对数组元素初始化的值
格式:
类型 数组名[元素个数] = {值1,值2,值3};
完全初始化:
类型 数组名[元素个数] = {值1,值2,值3 == 元素个数};
对数组中每个元素都进行初始化赋值,会按照值的顺序依次对数组元素进行初始化
float price[5] = {1,2,3,4,5};
部分初始化:
类型 数组名[元素个数] = {值1,值2,值3 < 元素个数};
按照顺序 依次初始化 数组中前几个值,未初始化 会有编译器初始化为0
float price[5] = {1,2,3}
指定初始化:
类型 数组名[元素个数] = {[下标] = 值1,[下标] = 值2,[下标] = 值3};
float price[5] = {[0] = 1,[4] = 2,[2] = 3};
在进行初始化时,由于会编写元素值,可以使用值的个数来表示元素个数,在定义的位置元素个数可以不写
类型 数组名[] = {值1,值2,值3};----虽然不写,但是有值的个数个元素
练习:在数组中输入10个数,找到数组中最大的元素以及存储的下标位置
二维数组:一维数组的集合,集合中的数组元素是一维数组
例:二维数组有 5个一维数组元素,二维数组每个元素(一维数组)又包含8个数据
定义:
数据类型 数组名[常量表达式1][常量表达式2];
数据类型:一维数组的元素数据类型
常量表达式1:二维数组的元素个数(有几个一维数组)
常量表达式2:在二维数组中的一维数组的元素个数(一维数组中有几个元素数据)
当定义了二维数组,在内存中存储二维数组,是按照行顺序,即先存储第一行(二维数组第一个一维数组),在存储第二行(二维数组第二个一维数组)
数组名[二维数组下标]:二维数组中的某个一维数组
数组名[二维数组下标][一维数组下标]:二维数组中的一维数组的数据元素
把二维数组按顺序,从第零个一维数组依次进行初始化
数据类型 数组名[常量表达式1][常量表达式2] = {值1,值2,值3,....};
int a[2][4] = {1,2,3,4,5,6};
把二维数组,每个{}表示初始一个一维数组
数据类型 数组名[常量表达式1][常量表达式2] = {{值1,值2},{值3,.}...};
int a[2][4] = {{1,2},{5,6,7}};
对于二维数组初始化时可以不指定一维数组的个数
即:数据类型 数组名[][常量表达式2] = {};
int a[][3] = {1,2,3,4,5,6,7,8};-------有3个一维数组
shell命令、文件管理、服务器的配置(tftp、nfs)、shell脚本
通常Linux就指代的是Linux内核:能够让计算机跑起来
Linux操作系统:
Linux内核 + 应用/系统软件 构成方便用户进行操作使用的系统
Linux内核 开源,支持多任务、多用户
Linux是免费开源的内核程序
Linux操作系统:
ubuntu
debian
deepin
red hat
centos
Linux内核
shell:命令解释器,通过shell提供内核的功能
文件系统
应用程序
内核是linux系统中最底层,提供系统中核心功能并允许有序访问硬件资源
用于管理:
输入输出设备、进程的执行情况、文件系统的操作、内存管理
linux内核支持:
多任务、多用户
文件系统就是用于组织和管理计算机存储设备上的大量文件
windows中使用NTFS文件系统格式
linux中格式多,目前通用EXT4文件系统格式
linux文件系统的逻辑结构(linux目录结构):
linux中 文件系统把文件组织为倒置的树,每一个文件夹(目录)当做树的分支
文件系统只有一个起始点叫做根: / ---根
Linux文件系统把一切所有内容都看做文件,Linux一切皆文件
Linux文件系统就是一个 树形的目录结构:
将 / 作为整个文件系统的起点,其他的所有目录都是从根开始
Linux文件系统存储文件:
/:根目录
/bin:存储系统中最常用的可执行程序
/boot:存储Linux系统启动文件
/dev:存储系统中的设备文件,包括硬盘、鼠标、键盘
/etc:存储系统配置文件,如passwd存储用户信息
/home:普通用户的家目录位置
/lib:存放共享库
/media:存储cd、软盘、usb临时读入的文件
/mnt:挂载的文件系统挂载点
/opt:作为可选程序和文件存放目录
/proc:当前执行的进程的文件存储目录
/root:超级用户的家目录
/sbin:作为扩展的,更多的二进制程序存储目录
/usr:标准库、第三方库存储目录
shell叫做命令解释器,当执行程序时,把程序中的各种操作命令进行解释执行,通过命令解释器让内核执行对应操作,可以提供一种用户与操作系统交互的方式
shell完成内核与用户之间的交互
shell命令:
向系统内核发出控制请求
shell解释器:命令解释器,将用户的命令解析为操作系统能够理解指令,实现用户与内核交互
shell命令的输入,在终端提示符,标识了命令的开始
终端提示符:
ubuntu@linuxmachine:~$
用户名分割符计算机名分隔符当前的工作路径用户权限
~:代表当前的用户的家(用户)目录
shell命令格式:
命令+选项+参数
command +[option] +[argument]
command:命令,shell要解析的内容,要执行的内容
option:改变命令执行动作的类型,选项使用 - 表示,可以有多个选项
argument:命令作用(执行)的目标
有时,命令不一定要携带选项和参数,通常表示使用默认的选项和参数
man command:查询手册找打command使用说明帮助
绝对路径与相对路径:
路径:找到某个文件,所经过的目录就叫做路径
绝对路径:从根目录(/)开始所经过的目录,指文件在文件系统中的准确位置
相对路径:从当前的工作目录开始,找到文件所经过的目录,指文件在当前的相对位置
~:当前用户的家目录
.:当前工作路径
..:当前路径上一级路径
pwd:用于查询显示用户当前的工作路径(用户在文件系统的位置路径)
pwd没有选项和参数
cd:改变用户当前的工作路径(改变工作目录)
cd新工作路径 切换当前的工作路径为新工作路径---新的路径必须要存在
cd------>cd ~
mkdir:创建目录文件,在指定路径下创建目录
mkdir创建目录路径
-p选项:如果父目录不存在则一起创建
rmdir:删除空目录
rmdir要删除的目录路径
ls:列出目录或文件的内容项
ls:列出当前工作目录的所有项内容
ls目录路径:查看对应目录所包含的项内容
选项:
-a:列出所有文件(包括隐藏文件)
-A:列出所有文件(包括隐藏文件,但是排除 . 和 ..)
-i:列出文件的inode号
-l:显示文件的详细信息(文件属性)
文件类型 |
文件权限 |
文件硬链接 |
文件所有者 |
文件所属组 |
文件大小 |
文件最后修改时间 |
文件名 |
-:普通文件 d:目录文件 p:管道文件 s:套接字文件 c:字符设备文件 b:块设备文件 l:符号链接文件 |
分为三组(每组三位): 所属用户, 所属组, 其他用户 |
相同文件的数量 |
当前文件所属的用户(即按照第一组权限访问) |
文件用户的组(即按照第二组权限访问) |
当前文件的大小字节 |
最后修改文件的时间 |
|
目录权限: r:能够查看目录中的文件-----ls w:能够在目录创建、删除、修改文件 x:能够访问进入目录--cd |
目录文件的硬连接数为子目录的个数 |
目录大小固定位4096 |
cat:读取指定文件的内容(查看文件)
cat文件路径
-E:在每行结束末尾添加$
-n:添加行号
head:查看文件前几行
head文件路径
显示前10行
-n:显示n行
tail:查看文件最后几行
tail文件路径
touch:创建一个普通文件
touch文件路径1文件路径2 文件路径3
在对应路径(必须存在)下创建文件
如果文件名存在,则改变文件的最后修改时间
file:判断文件类型
file文件路径
diff:比较两个文件的不同
diff文件1文件2
cp:将文件拷贝到指定目录中
cp源文件路径目标路径
cp源文件路径目标路径/文件名
选项:
-r:拷贝目录(会把目录中的所有文件都拷贝)
mv:将源文件移动到指定目录中
mv源文件目标路径
mv源文件目标路径/目标文件名
rm:删除指定路径下的文件
rm文件路径
选项:
-r:删除目录
链接文件:符号链接文件、硬链接文件
符号链接文件(软链接):创建一个快捷方式,操作符号链接文件就是操作员文件,但是删除符号链接对源文件无影响,删除源文件符号链接无法使用
ln-S源文件目标文件(符号链接文件--软链接文件)
硬链接文件:在文件系统中,创建一份与源文件完全一致的文件,创建的文件和源文件一致保持一致,但是删除其中一个文件对另一个文件无影响
ln源文件目标文件(硬链接文件)
修改文件权限(读、写、执行):执行命令的用户要求是对应要修改权限的文件的所有者,才能够修改(普通用户只有改修自己的所有文件的权限)
超级用户拥有改所有用户文件的权限
sudo:临时使用(获取)root用户身份(管理员权限)来执行指定命令
chmod权限文件
权限:
用数字表示,9位二进制权限(用八进制表示)
用字符表示:
u+[r、w、x] 表示用户部分添加对应权限
u-[r、w、x] 表示用户部分删除对应权限
g+[r、w、x] 表示用户组部分添加对应权限
g-[r、w、x] 表示用户组部分删除对应权限
o+[r、w、x] 表示其他用户部分添加对应权限
o-[r、w、x] 表示其他用户部分删除对应权限
在创建文件时默认权限:
普通文件:0664
目录文件:0775
改变文件的所属用户:只有管理员root才能修改
chown用户名文件
改变文件的所属用户组:只有管理员身份执行
chgrp用户组文件
linux压缩与解压:tar
压缩:先进行归档合并为一个文件,再进行压缩
解压:先进行解压操作,然后对归档文件进行释放
归档文件
创建归档文件:把多个文件打包成一个文件
tar-cvf归档文件名.tar文件1 文件2 文件3 文件4....
释放归档文件:把归档文件中打包的文件释放出来
tar-xvf归档文件名.tar
压缩与解压:
使用gzip算法对文件进行压缩与解压:-z
压缩:把多个文件先归档打包成一个文件然后使用gzip算法进行压缩
tar-cvzf压缩文件名.tar.gz文件1 文件2 文件3 文件4....
解压:
tar-xvzf压缩文件名.tar.gz
使用bzip2对文件进行压缩与解压:-j
压缩:
tar-cvjf压缩文件名.tar.bz2文件1 文件2 文件3 文件4....
解压:
tar-xvjf压缩文件名.tar.bz2
使用zip算法进行压缩
zip压缩文件名.zip 文件1 文件2 文件3 文件4....
使用zip算法进行解压
unzip压缩文件名.zip
输出重定向
>:指定输出到某个文件,会先清空对应位置的内容
>>:指定输出到某个文件,以追加方式输出到指定位置
输出到终端 > 文件
输出到终端 >> 文件
用户管理:
修改用户密码:
passwd用户名-----只能修改当前用户的密码
提升为管理员身份修改用户密码
sudopasswd用户名
切换用户:
su用户名
退出当前登录用户:
exit
创建新用户:只有root用户才能新建
sudo adduser新用户名
新建用户无sudo权限
如果需要添加sudo权限,则在sudoers 添加 新用户名
sudo vim/etc/sudoers
在文件最后添加:
新用户名 ALL=(ALL:ALL) ALL
删除用户:管理员删除
sudouserdel-r用户名
创建用户组:
sudogroupadd用户组名
将用户添加到用户组
sudogpasswd-a用户名用户组
查看用户对应的用户组
groups用户名
将用户从用户组删除
sudogpasswd-d用户名用户组
删除用户组:
sudogroupdel用户组名
1、直接执行二进制程序进行安装
2、软件包管理工具安装
解析 软件包,查找对应依赖环境,安装软件
debian linux 软件包机制-----解析.deb
red hat linux 软件包机制-----解析.rpm
a、本地离线安装(本地软件包管理)
dpkg:离线包管理
dpkg-i软件包名:安装软件
dpkg-r软件名
b、在线安装(在线软件包管理)
在线安装,在计算机中需要配置软件镜像源(软件从哪里下载)
/etc/apt/source.list 软件源地址列表
检查网络信息:
ping + ip地址或域名:查看是否与对应的ip地址或域名连通,测试网络连接是否正常
ifconfig:查询本机的网络信息(需要安装net-tools)
apt:在线包管理工具(apt-get)
apt就是用于获取、安装、编译、卸载、查询于一体的包管理工具,自动检查软件的依赖是否安装
apt软件管理使用:
sudo apt update:下载(获取)更新 软件源地址中的软件包列表
sudo apt install软件包名:下载安装对应的软件
sudo apt --reinstall install 软件包名:重新再次安装
sudo apt remove软件名:卸载对应的软件
sudo apt clean:清除下载的安装包
网络文件共享服务器:提供主机中目录用于共享,当客户端来连接这个服务器后,就可以使用我共享的目录
1、安装nfs服务器软件
服务器:nfs-kernel-server
sudo apt install nfs-kernel-server
2、修改nfs服务器的配置
因为服务器功能为共享 文件夹,所以要修改对应的共享文件夹目录
sudo vim /etc/exports-----nfs配置文件
添加:
/home/ubuntu/nfsserver *(rw,sync,no_subtree_check)
/home/ubuntu/nfsserver:要共享的文件夹目录
*:允许哪些客户端的ip地址访问nfs服务器
rw:读写
sync:同步更新
no_subtree_check:不检查父目录权限
如果共享目录不存在,则创建对应目录,设置权限
mkdir目录路径
3、启动nfs服务器
设置服务器端口为监听状态(开启监听)
sudo service rpcbind start
启动nfs服务
sudo service nfs-kernel-server [start、restart、status、stop]
4、查看nfs共享的目录
showmount -e
5、客户端连接
linux:
mount -t nfs 服务端ip:/home/ubuntu/nfsserver /mnt 挂载位置
umount/mnt
windows:
连接:
mount \\服务端ip\home\ubuntu\nfsserver(绝对路径) X:(挂载到windows哪个盘)
断开:(解除挂载)
umount X:
tftp:文件上传下载服务器
tftp:tftp文件上传下载服务器功能,提供一个文件夹(目录),可以让其他的客户端从这个目录下载文件,或上传文件到这个目录
tftp服务器:
1、安装tftp服务器
sudo apt installtftpd-hpa
tftp-hpa(客户端)
提供了服务端功能:上传、下载
2、配置tftp服务器提供的操作功能(修改配置文件)
sudo vim /etc/default/tftpd-hpa
文件内容:
TFTP_USERNAME="tftp"--------服务器程序名
TFTP_DIRECTORY="/srv/tftp"-------提供的可以进行上传下载的目录(只能把文件上传到这个目录和从这个目录下载文件)
TFTP_ADDRESS="0.0.0.0:69"------服务器的tftp程序的地址
TFTP_OPTIONS="-l -c -s"
3、启动tftp服务程序
sudo service tftpd-hpa start
restart
status
客户端进行上传文件到tftp服务器,从服务器下载文件
sudo apt install tftp-hpa
使用:
tftp服务端地址
tftp> put 文件名:上传文件
tftp>get 文件名:下载文件
tftp>q:退出tftp客户端
通配符 |
作用 |
例子 |
*(星号) |
可以表示匹配任意的字符串 |
1*2.txt:表示可以匹配1开始以2.txt结束的所有名字:123456782.txt,1abc2.txt |
?(问号) |
匹配一个长度的字符(只一个字符) |
file_?.txt:可以匹配 file_开始 中间只有一个字符,以.txt结束的名字:file_1.txt(可以),file_12.txt(不可以) |
[匹配字符](方括号) |
从方括号中取一个匹配字符进行匹配 |
file_[abc123].txt:只能匹配以file_开始,中间是[abc123]其中一个字符,以.txt结束的名字:file_a.txt(可以),file_5.txt(不可以) |
[起始范围-结束范围](方括号) |
从方括号中取一个对应范围内的字符进行匹配 |
file_[a-k].txt:只能匹配以file_开始,中间是a - k其中一个字符,以.txt结束的名字: file_a.txt(可以),file_z.txt(不可以) |
[^不匹配字符](方括号) |
除了方括号中的字符,其他字符匹配一个 |
file_[^abc].txt:除了a、b、c字符其他字符可以进行匹配一个:file_1.txt(可以匹配),file_e.txt(可以),file_a.txt(不可以) |
将shell命令按照一定的逻辑关系,顺序组织在一个文件中,组合成一系列完整的功能要求,执行文件,就可以其中shell命令按照对应的逻辑顺序执行
shell文件是以.sh作为后缀名
执行shell脚本(文件):
1、为shell脚本文件,添加可执行权限,按照可执行文件的方式执行
修改为包含可执行权限
chmod权限文件
可执行文件,怎么执行
可执行文件的路径+文件
/home/ubuntu/linuxC/day3/1.sh
./1.sh
2、使用对应的shell解释器来解析执行
在当前ubuntu安装使用的是bash shell解释器
bash文件名.sh
在shell文件中,通常先添加shell解释器的版本说明(使用哪种解释器)
#!/bin/bash:说明,使用哪种解释器来解析
shell语法:实现shell脚本的逻辑功能
1、变量定义
定义:
变量=值
引用变量:
$变量
在字符串中中可能会出现要使用变量名情况:
“”:会解析引用的变量
'':不会解析引用的变量
2、变量的输入
在shell脚本中,使用 read 表示 输入字符串 到变量中:
read变量1 变量2 变量3.....
shell脚本存在特殊变量,位置变量:
$1:获取执行shell脚本文件时,命令行传递的第一个参数
$2:获取执行shell脚本文件时,命令行传递的第二个参数
$3:获取执行shell脚本文件时,命令行传递的第三个参数
...
$9:获取执行shell脚本文件时,命令行传递的第九个参数
$@ / $*:获取命令行传递的所有参数
$?:获取上一条命令执行的状态值,上一条命令执行成功$?的值为0,否则非0
3、条件判断
判断条件: test
字符串:s1,s2就表示字符串
s1 = s2 :判断相等
s1 != s2 :判断不等
-z s1 :判断字符串长度是否等于 0
-n s1 :判断字符串长度不为0
整数:a,b表示数字字符串
a -gt b :判断a 是否 大于 b
a -ge b :判断a 是否 大于等于 b
a -lt b : 判断a 是否 小于 b
a -le b :判断a 是否 小于等于 b
a -eq b :判断a 是否 等于 b
a- ne b :判断a 是否 不等于 b
文件测试:
-d filename:判断filename是否是一个目录
-e filename:判断filename文件是否存在
-f filename:判断filename文件是否是普通文件
-L filename:判断filename文件是否是符号链接文件
-s filename:判断filename文件存在且长度不为0
-r filename:判断文件存在且是否可读
-w filename:判断文件存在且是否可写
-x filename:判断文件存在且是否可执行
4、逻辑运算
条件1 -a 条件2 :逻辑与,多个条件都为真,结果为真
条件1 -o 条件2 :逻辑或,只要有一个条件为真,结果为真
!条件:得到条件取反
5、if选择结构
语法1:如果满足条件表达式,则执行命令,不满足就跳过
if [ 条件表达式 ]
then
命令
fi
语法2:如果满足条件表达式,则执行命令1,不满足则执行命令2
if [ 条件表达式 ]
then
命令1
else
命令2
fi
语法3:如果满足条件表达式1,则执行命令1,不满足则判断表达式2,满足则执行命令2,不满足则判断表达式3,满足则执行命令3,不满足则判断表达式4,.......直到最后一个条件为止
if [ 条件表达式1 ]
then
命令1
elif [ 表达式2 ]
then
命令2
elif [ 表达式3 ]
then
命令3
....
elif [ 表达式n ]
then
命令n
else
以上都不满足则执行
fi
6、循环
算数运算指令:expr
`expr $1 + $2`
while [ 条件表达式 ] ------ 当满足条件就执行一次
do
命令表
done
for 变量名 in 单词表-------如果变量名能够从单词表中取出一个值(单词),就执行一次循环
do
命令表
done
c语言for循环格式
for((循环初始语句;循环条件语句;条件改变语句))
do
命令表
done
函数:实现一个完整的功能步骤,需要时直接使用
函数定义:
函数名()
{
命令集合
}
函数调用:
函数名
函数参数:
如果函数定义需要参数 ,函数的()中不用写参数,使用位置变量$1,$2,$3.... 作为函数的参数,来传递参数值
函数调用时:
函数名参数值1 参数值2 参数值3,,,,,
函数返回值:
在函数中执行 echo 命令 输出显示,只要当调用时 有赋值,这时echo 为返回值
指针、构造类型、动态内存管理、多文件与关键字
是直接访问内存的方式
内存地址:在内存空间中,对每一个字节都分配了一个唯一的编号,用于区别不同的位置。每个字节都有唯一的地址,用来和内存中的其他字节相区别
指针:在内存空间(定义变量)申请空间来存储地址,就叫做指针,也叫做指针变量
指针就是操作内存地址,使用内存地址
指针变量:本质就是一个变量,存放的是一个内存地址
指针变量定义的形式:
指向数据类型 * 指针变量名;
指向数据类型:存储哪种类型数据的地址,指向哪种类型
指针变量:定义一个变量,用于存储地址,如果要存储哪种类型的地址,数据类型就是对应的类型
存储地址:
指针变量 = 地址(要求地址的空间能够使用)
变量的地址获取:通过 & 取地址运算符,得到变量的地址
指针变量 = &变量
指针变量访问内容:操作对应地址的数据,通过地址的方式访问数据
用变量名来表示代表变量中的值
用指针来访问变量:
*指针名 访问对应地址(指针存储的地址)的数据空间
int * p;
p = &a;
*p ; // ==== a 表示访问 p存储的地址(即a的地址),对应空间的空间
指针变量赋值地址:通过指针建立与对应内存空间联系
指针 取*:得到建立联系的内存空间的值
指针变量的初始化:
在定义指针变量时,进行赋值,就叫做初始化
类型 * 指针名 = 地址;
野指针:
指针记录的地址不明确(存储的地址不知道,或地址对应空间是否具有操作权限不确定),这种指针叫做野指针
野指针不需要直接进行 取 *
空指针:
指针记录的地址是NULL(地址:0x00),系统规定NULL地址不允许进行操作
只要操作就会报错
空指针通常表示,该指针当前不可用
万能指针:
void * 类型指针变量,可以存储任意类型的地址,也可以把指针赋值给其他的任意类型指针变量
void * 指针,指针存储地址,不能进行 取值操作(取 *),因为指向的类型未知不明确
指针 + / - 整数,表示移动指针 指向 的位置
+:
指针 + 整数n
往地址增大方向,移动 n 个 指向(指针指向,指针存储哪种地址)的数据类型 大小
int * p;
p + 5 ==== >移动 5 * 4
指针 + n == 指针 + n * sizeof(指向类型)
-:
指针 - 整数
往地址减小方向,移动指针指向类型(指针存储哪种类型地址)的大小 * 整数大小
指针 - 整数 * sizeof(指向类型)
指针++:
先使用指针,然后 指针 = 指针 + 1
++指针:
先 指针 = 指针 + 1 ,然后再使用指针
指针--,--指针
指针 - 指针:
获取两个指针之间间隔多少个对应类型的数据
(指针 - 指针) / sizeof(指向类型)
一维数组是一段连续的空间存储多个数据元素,在数组中相邻的元素,间隔大小为每个元素类型的大小,即 &数组名[元素i] == &数组名[元素i-1] + 类型大小
指针能够进行运算,指针 + 1,移动一个数据类型的大小,即 指针 + 1 == 指针 + 指向类型大小
如果指针变量存储了数组中的元素地址,指针+1 ,就是数组中下一个元素的地址
指针与数组的操作方式:
可以通过指针访问整个数组
只要知道数组的起始地址(第零个元素的地址),就可以遍历整个数组
数组首地址:数组的起始地址,就是第零个元素的地址
int * p = &a[0];
*(p+n) == a[n]
在数组中,数组名 有个特殊作用。数组名就表示 数组的首地址
数组名,地址常量
int a[5];
a == &a[0]
数组首地址(数组名) + n:偏移n个数据元素大小
*(数组名 + n) == 数组名[n]
*(a + 3) == a[3]
基于数组名(常量地址),可以将数组名当做指针进行使用,除了不能赋值运算(a = a+1)
因为数组名可以表示数组首地址,而指针变量也可以存储数组首地址,在访问数组的操作时,指针变量和数组名作用一致,所以
数组名[n]:访问数组的n元素 ==== 指针名[n]
int *p,a[5];
p = a;
p + n == a + n//等价
a[n] == *(p+n) == *(a+n) == p[n]
基于指针变量,可以将指针当做数组用,不能越界
字符串与字符数组
字符串:有多个字符组成一个连续且有序的字符序列
"abcdef"------字符串
C程序中,通过字符数组来存储字符串
字符数组通过访问数组中的元素,就是访问字符串(按照字符数组,每个元素单独访问)
如果需要整体访问字符数组中存储的字符串,要求在字符串结束的下一个字符位置存储'\0'
'\0'字符就表示 字符串的结束
字符数组存储字符串:
字符数组初始化存储字符串
char数组名[大小] = "字符串";
注意通常,在进行输入前把数组初始化全为'\0'
输入字符串到字符数组中
scanf("%s",数组名/首地址);
输出打印字符数组中的字符串
printf("%s",数组名);
常量字符串表示:
"acbde"-----常量字符串
在常量字符串中,在最后字符后默认包含'\0'字符
在程序中如果写出常量字符串,则常量字符串表示常量字符串的首地址(第零个字符地址)
如:“abccde”,得到就是字符串的首地址,地址常量
地址,指针类型,都是统一的大小,各个类型之间没有区别
32位机器:4B
64位机器:8B
练习:
1、在数组中有10个数,统计10个数的和(通过指针)
2、输入一个名字,计算是否存在 'x'字符(指针)
作业:
1、输入一个字符串,求字符串的长度
2、输入两个字符串到两个数组中,然后把两个字符串进行拼接
二维数组:二维数组中,每个元素是一个一维数组,在元素(一维数组)中,每个成员就是一个值
二维数组:
数据类型数组名[行][列]
行:有多少个一维数组
列:一维数组的元素个数
对于二维数组而言,数组名是整个二维数组的首地址,第零个元素的地址,二维数组的元素都是一维数组,即二维数组数组名表示其中元素,整个一维数组的地址。
int a[3][4];
a == &a[0];//a[0]是整个一维数组
由于a表示整个元素的地址(一维数组的地址),所以进行指针运算时,+1 ,加上 整个一维数组大小
a:&a[0],第零个一维数组的地址
a+1:&a[1],第一个一维数组的地址
a+2:&a[2],第二个一维数组的地址
a[0]:表示二维数组的元素零,第零个一维数组,a[0]是一维数组的数组名,在这个一维数组的首地址
a[0] == &a[0][0]
a[0]+1 == &a[0][1]
a[1]:第一个一维数组,也是这个一维数组的数组名(首地址)
a[1] == &a[1][0]
a[1]+1 == &a[1][1]
注意:
a+1,表示移动二维数组的一个元素(一维数组)大小
a[0]+1,表示移动一维数组的一个元素(数据类型值)大小
数组指针:
是一个指针,指针用于存储整个数组的地址,指针的指向类型为数组
定义:
数组元素类型 (* 指针变量名)[大小];
int (*p)[4];//定义一个指针变量,指针变量存储 整个数组的地址(int [4])
数组指针和二维数组名是等价的,因为二维数组表示第零个元素(一维数组)的地址
int a[3][4];
int (*p)[4];
p = a;//&a[0]
p+1 == a+1 == &a[1]
*(p+1) == a[1]
*(p+1)+2 == &a[1][2]
*(*(p+1)+2) == a[1][2]
指针数组:
是一个数组,只是每个元素为指针类型
指向类型 * 指针数组名[元素个数];
int * p[5];
定义 包含 5个元素 每个元素为指针(int *)
int a;
p[2] = &a;
多级指针:
一级指针:存储变量的地址
二级指针:存储一级指针的地址:一级指针类型 * 指针名;
三级指针:存储二级指针的地址:二级指针类型 * 指针名;
......
指向类型 * 指针名;
int **p;
int * a[10];
p = a;
p+1 == a+1;
*(p+2) == a[2]
二级指针与指针数组名等价
作业:
1、定义一个字符二维数组,输入要存储‘#’号的个数,然后分别输入存储的位置,其他位置默认存储 ‘ ’空格字符
2、二维数组和数组指针
int a[2][3];
int (*p)[3] = a;
在以下每个表达式中,p = a,求表达式的含义
a[0]
a[0][2]
*p
**p
*a
**a
*p++
**(p+1)
*(p+1)+1
*(*(p+1)+1)
3、定义二维数组,输入数据,然后求每个元素中的最大值
4、字符串的替换,输入一个原字符串,然后输入要替换的起始位置,输入新字符串进行替换
指针作为函数的参数:可以表示变量的地址,或者是数组名/数组首地址,作用就是表示参数为地址
把地址作为参数进行传递
返回值类型 函数名 (指针参数1,指针参数2); 接受传递的是地址
调用:
函数名(地址,地址/指针);
如果是数组作为形式参数,会由编译器自动变为对应类型指针
int sumarray(int p[10],int length) p就是指针 int*
指针作为函数返回值:返回一个地址,把指针作为函数的结果返回
函数指针:指针存储是的函数的地址
函数的类型表示:
返回值类型(参数1,参数2,参数3,......);
int (int a,char b);-1
int (int a,int b);-2
int (int c,int d);-3
1和2是不同函数类型,2和3是相同函数类型
函数指针表示:
返回值类型(* 指针变量名)(参数1,参数2,参数3,......)
函数地址:
函数名就是用于表示函数的地址
函数指针 = 函数名;
调用函数:
通过函数指针进行调用
函数指针名(实参);
由于基本数据类型不能满足需要,需要把多个的数据类型进行组合,共同表示新的复合数据,形成新的类型。构造新的数据类型的方式就叫做构造类型
使用多种数据类型作为成员,进行组合,构成的新的类型,就叫做结构体
声明结构体:结构体的类型表示
struct结构体名字
{
类型1 成员1;
类型2 成员2;
类型3 成员3;
....
};
在程序中添加一种新的类型,不占用内存空间,只是说明在程序中有一中新类型
定义结构体变量:
struct结构体名字 变量名;
对结构体变量的操作,就是对结构体变量的成员进行操作
结构体变量访问成员:
结构体变量名 . 成员名;
结构体变量初始化:
在定义结构体变量时,对其成员进行初始化
顺序对成员初始化:
struct结构体名变量名 = {成员1值,成员2值,成员3值,......};
指定成员初始化:
struct结构体名变量名 = { .成员名2 = 成员值,.成员名4 = 成员值,......};
结构体指针如何访问变量的成员:
结构体指针:
struct结构体名* 指针名 = 结构体地址;
访问方式:
指针->成员://访问结构体指针对应地址中的成员
(*指针).成员 == 指针->成员
结构体特殊的声明方式:
struct结构体名字
{
类型1 成员1;
类型2 成员2;
类型3 成员3;
....
}结构体变量名;--------在声明时同时定义结构体变量
struct
{
类型1 成员1;
类型2 成员2;
类型3 成员3;
....
}结构体变量名;--------在声明时同时定义结构体变量,但是之后不能使用这个声明进行定义变量
使用多种数据类型作为成员,进行组合,但是使用同一段空间存储(多个成员共用一个空间),构成的新的类型,就叫做共用体
使用共用体的问题:同一时刻只能操作一个成员
声明共用体类型:
union 共用体名
{
类型1 成员1;
类型2 成员2;
类型3 成员3;
....
};
用法:共用体与结构体一致
枚举就是定义一种新类型时,这个类型能够取值的范围是确定的,通过这个定义的新类型把能欧取值的范围一一列举出来,这种类型就叫做枚举
声明枚举类型:
enum枚举名
{
成员1,
成员2,
成员3,
......
};
枚举类型中,每个成员就代表能够取的一个值
声明类型时,如果成员没有赋值,成员就等于上一个成员的值+1,如果成员1没有赋值则为0
定义枚举变量:
enum 枚举名变量名;
变量名 = 成员;
#include
//把src首地址的字符串,拷贝到dest首地址中
char *strcpy(char *dest, const char *src);
//把src首地址的字符串前n个,拷贝到dest首地址中
char *strncpy(char *dest, const char *src, size_t n);
//比较字符串s1 和 s2 是否相等,如果相等返回0,如果不等返回当前字符的差值
int strcmp(const char *s1, const char *s2);
//比较字符串s1 和 s2 的 前n 个字符 是否相等,如果相等返回0,如果不等返回当前字符的差值
int strncmp(const char *s1, const char *s2, size_t n);
//计算 s 字符串的字符个数(不算'\0'),返回值就是字符串的长度
size_t strlen(const char *s);
//把src字符串 拼接到 dest字符串后
char *strcat(char *dest, const char *src);
//把src字符串 前n个字符 拼接到 dest字符串后
char *strncat(char *dest, const char *src, size_t n);
栈中变量,只要离开了变量的生命周期,变量就会由系统销毁释放
堆空间:有程序员在程序中,自己进行管理的空间,需要使用时进行申请,由自己进行释放销毁。空间的申请与释放都是由程序员在程序中指定,通过地址指针进行访问空间,根据指针的类型就按照对应类型进行访问,就叫做动态内存
申请空间:
#include
malloc函数在堆空间中申请指定大小的内存空间
void *malloc(size_t size);
参数:
size_t size:要申请的字节数
返回值:
void *:如果申请成功,返回申请的空间首地址
如果申请失败,返回NULL地址
释放空间:
#include
free就是释放malloc申请的空间
void free(void *ptr);
参数:
void *ptr:申请空间的首地址,进行释放空间
const:
在定义变量时,使用const关键字修饰,变量不可修改,作用类似于常量
const数据类型变量名;
通常情况下const变量要进行初始化
const修饰指针变量时,有不同的用法:
指向类型 * const 指针变量名;
表示指针变量不可修改,但是指向地址中的内容可以修改
指针变量不可改;
*指针变量 可以修改;
指向类型 const * 指针变量名;/ const 指向类型 * 指针变量名;
表示指针变量可以修改,但是指向地址中的内容不可修改
指针变量可改;
*指针变量 不可改;
const 指向类型 * const 指针变量名;
指针变量不可改;
*指针变量 不可改;
static
修饰局部变量
修饰全局变量
auto
自动类型,定义在栈中,由系统进行管理
register
定义变量在cpu中,如果没有成功则与auto相同