【知识点1】基本的linux命令操作,操作通过命令来实现
1、 cd:切换目录 切换到某一个文件夹里面去
首先我们要建立一个共享目录,我们写代码更希望用软件在windows下面写
但是最后我们的编译和运行都需要在linux里面,因此我们就需要让windows和linux
之间有一个交流->共享文件夹->这个文件夹里面的东西在windows里面可以操作
在linux里面也可以操作
① player -> 管理 -> 虚拟机设置 -> 选项 -> 共享文件夹 -> 选择总是启用
-> (将里面的文件夹先移除) ->添加->下一步->浏览->找一个自己喜欢的文件夹
或者新建一个(不要在c盘里面操作) ->尽量用英文(文件夹的名字中间尽量不要有空格)
-> 下一步完成确定就可以了
②切换到共享目录
cd /mnt/hgfs/D 在打字的过程中可以按table键自动补齐
2、 我们需要在终端里面操作(黑色的那个框,可以ctrl+alt+t三个组合键打开一个终端)
每一个文件夹里面隐藏两个特殊的文件夹
. 当前目录
.. 上一级目录
cd .
cd ..回到上一级
相对路径与绝对路径:
绝对路径:我们的linux是树形结构 有唯一的一个根 / 表示
从/出发的都是绝对路径
相对路径是从. ..出发的我们叫相对路径
cd ./22248/1.9数据类型/code -> 我们可以省略./
cd 22248/1.9数据类型/code //也可以起到同样的效果
cd ../22248/1.9数据类型/code (这个我还是不太会用)
ls:列举当前目录下面的所有东西
ls
ls -a隐藏的也列举
ls -l以列表列举
ls -al所有的以列表列举
gcc:常用的编译器(大多数使用这个编译器)
gcc main.c -o hehe //这种方式可以自己命名
gcc main.c ->默认生成a.out
找到这个可执行文件即可执行
./a.out 回车即可执行
小总结:
1 切换到共享目录
2 写代码 ->可以用自己喜欢的写代码的软件
3 gcc编译这个代码
4 运行生成的可执行文件
【知识点2】数据类型:
1、问题:
计算机只是人类设计出来解决问题的一个工具,实际上是一个很简单的概念:
计算机只会计算,不会思考
因此你让计算机怎么做它就怎么做,如果计算机做错了,你只能找你自己的原因
计算机怎么去做计算:在计算机里面有一个寄存器 -- 加法器
计算机里面的一切计算都是通过这个加法器来实现的
因此:计算机在计算的时候就必须需要两个对象(数据)、
至少要给两个数据才能去做加法
我们人类做加法也需要数据 -- 这个数据是保存在大脑里面的
计算机也是一样,它想做加法,它就要必须要将所需要的数据保存下来
而保存数据的地方在计算机里面 -> 内存 ->计算机保存数据的地方
程序操作计算机实际上就是操作内存
计算机只能操作内存,那么它就必须要知道内存是什么
换一句话说 -> 计算机必须知道这个数据有多大
内存 -> 内存条(8G)
我们操作的这个数据保存的地方就是这个内存条
如果我们不指定大小 -> 计算机就会将整个内存条里面的东西拿出来
你拿了没有问题,但是系统不允许
举例:100 1000 10000//数字
不同的数据占用的空间不一样
因此想要计算机运行,第一步就必须要让计算机知道你的数据的大小
2、c语言里面是如何去确定这个数据的大小呢?
"定义"--也就是c语言想要运行,第一步就必须要确定数据的大小
而确定数据的大小的过程我们就叫定义,因此c语言也叫"定义性语言"
c语言里面的数据类型:
(1) 基本的数据类型:c语言已经给我们定义好了的,我们只需要拿过来用就可以了
1 整型 ->保存整数
(signed)char/unsigned char 字符型
占用 1byte -> 8bit -> 计算机里面的最小存储单位是字节//只有字节才有地址
(signed)short/unsigned short 短整形
占用 2byte -> 16bit
(signed)int/unsigned int 整形
占用 4byte -> 32bit-> int一般为计算机里面最自然的长度
(signed)long/unsigned long 长整形
32位机4byte
64位机8byte
(signed)long long/unsigned long long 长整形
8byte
在现实中有那种特别大的数 -> 大数据
这种大数据我们一般的处理方式是字符串 "......"
2 浮点型 ->保存小数
float 单精度 4byte
double双精度 8byte
long double 长精度
eg:
float a;
a = 3.15
(2) 构造类型:c语言里面允许程序员自己定义类型
数组 int a[3]; -> int[3] a;
数据类型 变量名;
结构体 -> 描述一个物体的多重属性
struct hehe
{
int a;
char * p;
char c;
};
联合体
枚举
(3) 指针类型(后续有很长的时间去专门搞这个玩意儿)
*
int * p;
(4) 空类型(void)
c语言里面只有三个地方会使用这个void
1 void * 万能指针,什么指针都可以接收
2 void用作函数的返回值,表示此函数没有返回值
void function()
{
.......
return;//这个return后面没有值
}
注意:
没有返回值不代表不返回
3 void用作函数的参数,表示此函数没有参数
void function(void)
{
}
高级一点的编译器已经不需要你写函数参数里面的void
但是在低级编译器里面如果你不写会有警告
整个数据类型定义基本就完了
接下来我们就要通过这些数据类型去定义(保存)数据
c语言里面的,有两种基本的数据对象:常量,变量
【知识点3】常量
1 常量:不能改变意思的这种数据对象
比如有一个数8:你能改变8的意思吗?
你是不能改变8本身自己的意思的
8只能代表8的意思,因此这个8就是常量
1 整形常量:代表一个不能改变意思的整数
8进制:以0开头的我们是8进制
0123
01237
01238是错的 到不了8的
逢8进1
8进制 二进制
0 000
1 001
2 010
3 011
4 100
5 101
6 110
7 111
后续我们经常会碰到一个8进制的数:0664
我们的linux对一个文件有一个权限的描述
而这个权限又是三个组
1 user使用者本身
2 group使用者所在组
3 other其他用户
每一种权限都会对应三种权限 r w x 读写可执行
每一个权限如有那么就是1 没有就是0
16进制:0x开头的表示为16进制 x可以大写
满16进1 而我们如果仅仅使用10进制的数字去表示16进制不够
因此我们大于等于10的数字用 ABCDEF去表示
A表示的是10
.....
F表示的是15
字母也不分大小写
每4个bit为一个16进制的数字
0x123
0xabc
0x123acf//没有满足也就不管,前面的在前面,后面的在后面
例如0xff -> 1111 1111
0xff1-> 1111 1111 0001
16进制 二进制
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
a 1010
b 1011
c 1100
d 1101
e 1110
f 1111
两个16进制的数字表示1个字节
0xfd -> 一个字节
0x1234 -> 两个字节
其余的都是10进制
2 字符常量
计算机里面是没有字符的形状的,也就是保存这个字符不是保存的这个字符的形状
而是给这些字符一个编码,一个编码代表了一个字符
这个编码我们叫ASCII码
这个ASCII码实际上就是一坨的整数,也就是我们在计算机里面用一个整数
来代表一个字符
Oct Dec Hex Char Oct Dec Hex Char
────────────────────────────────────────────────────────────────────────
000 0 00 NUL '\0' 100 64 40 @
001 1 01 SOH (标题开始) 101 65 41 A
002 2 02 STX (本文开始) 102 66 42 B
003 3 03 ETX (本文结束) 103 67 43 C
004 4 04 EOT (传输结束) 104 68 44 D
005 5 05 ENQ (请求) 105 69 45 E
006 6 06 ACK (确认回应) 106 70 46 F
007 7 07 BEL '\a' (响铃) 107 71 47 G
010 8 08 BS '\b' (退格) 110 72 48 H
011 9 09 HT '\t' (水平定位符号) 111 73 49 I
012 10 0A LF '\n' (换行键) 112 74 4A J
013 11 0B VT '\v' (垂直定位符号) 113 75 4B K
014 12 0C FF '\f' (换页键) 114 76 4C L
015 13 0D CR '\r' (Enter 键) 115 77 4D M
016 14 0E SO (取消变换) 116 78 4E N
017 15 0F SI (开始变换) 117 79 4F O
020 16 10 DLE (跳出数据通讯) 120 80 50 P
021 17 11 DC1 (设备控制1) 121 81 51 Q
022 18 12 DC2 (设备控制2) 122 82 52 R
023 19 13 DC3 (设备控制3) 123 83 53 S
024 20 14 DC4 (设备控制4) 124 84 54 T
025 21 15 NAK (确认失败回应) 125 85 55 U
026 22 16 SYN (同步用暂停) 126 86 56 V
027 23 17 ETB (区块传输结束) 127 87 57 W
030 24 18 CAN (取消) 130 88 58 X
031 25 19 EM (连接介质中断) 131 89 59 Y
032 26 1A SUB (替换) 132 90 5A Z
033 27 1B ESC (退出键) 133 91 5B [
034 28 1C FS (文件分区符) 134 92 5C \ '\\'
035 29 1D GS (群组分隔符) 135 93 5D ]
036 30 1E RS (记录分隔符) 136 94 5E ^
037 31 1F US (单元分隔符) 137 95 5F _
040 32 20 SPACE 140 96 60 `
041 33 21 ! 141 97 61 a
042 34 22 " 142 98 62 b
043 35 23 # 143 99 63 c
044 36 24 $ 144 100 64 d
045 37 25 % 145 101 65 e
046 38 26 & 146 102 66 f
047 39 27 ′ 147 103 67 g
050 40 28 ( 150 104 68 h
051 41 29 ) 151 105 69 i
052 42 2A * 152 106 6A j
053 43 2B + 153 107 6B k
054 44 2C , 154 108 6C l
055 45 2D - 155 109 6D m
056 46 2E . 156 110 6E n
057 47 2F / 157 111 6F o
060 48 30 0 160 112 70 p
061 49 31 1 161 113 71 q
062 50 32 2 162 114 72 r
063 51 33 3 163 115 73 s
064 52 34 4 164 116 74 t
065 53 35 5 165 117 75 u
066 54 36 6 166 118 76 v
067 55 37 7 167 119 77 w
070 56 38 8 170 120 78 x
071 57 39 9 171 121 79 y
072 58 3A : 172 122 7A z
073 59 3B ; 173 123 7B {
074 60 3C < 174 124 7C |
075 61 3D = 175 125 7D }
076 62 3E > 176 126 7E ~
077 63 3F ? 177 127 7F DEL
上述描述的字符和前面的整数是完全对等的
'A' == 0X40 == 65 == 0101
在c语言里面的使用''引起来的都是字符(重点!!!)
定义一个字符我们使用(unsigend)char去定义
char a = 'A';
or:char a = 65;
字符里面有几个特别需要注意的地方:数字字符
char a = '1';
char b = 1;
a != b
c = a + 1; -> c = 50;
d = b + 1; -> d = 2;
如果我们想用字符串表示出来的一个整数去做运算 我们一定要将这个字符串转换为整数才可以
char p[4] = "123";
p + 234;这是错误的
int d = (p[0] - '0')* 100 + (p[1] - '0')* 10 + (p[0] - '0');
上述运算之后d才会等于能运算的数字123
多个字符组合在一起形成字符串:c语言里面表示一个字符串,用""引起来多个(也可能是0个)字符我们就叫字符串
注意******:字符串的末尾必带\0 ,也就是"abc",后面会跟一个\0
char a[] = "abc"; -> char a[4] = "abc";
char b[3] = "abc";
上面的a是有\0,因此这个字符串是有结尾的,->字符串到\0就结束了,不管后面还有没有字符
char c[] = "abc\0def";//输出结果为:adc
上面的这个b就不能称为字符串,我们只能说叫字符数组,因为上面的b后面不一定是\0
因此这个字符串很有可能还没有完
字符串也是一个常量
字符里面有些比较特殊的存在:转义字符
本身代表的不是他自己的意思
'\n' -> 换行(新起一行)
'\r' -> 回车(回到开头)
很多时候换行不是'\n',是'\r''\n'两个字符
'\t' -> tab
....
转义字符实际上转义是看的\
有的时候我们又希望打印出\
这个时候我们要怎么操作?
'\\'
'\'' ->这个时候才可以表示'这个字符
'\"' ->这个时候才可以表示"这个字符
说明:(小重点!!)
打印字符用%c
打印字符串用%s
打印整数%d
打印地址%p
打印16进制%x
打印小数%f
'\ooo':由\加一个、两个、三个8进制的数字组成的,
代表的意思就是这个8进制的数字代表的那个字符
char c = 'A';
char c = '\101'
'\xhh':有\x后面加上一个、两个16进制的数字组成的,
代表的意思就是这个16进制的数字代表的那个字符
char c = 'A';
char c = '\101'
char c = '\x41'
char c = 65
char c = 0x41
char c = 0101
3 浮点型常量
由整数部分,小数点,小数部分表示的
一个e/E,一个可选的带符号的整形的指数部分和一个可选的表示整形的后缀组成
3.14e5
整数部分可以没有
小数部分也可以省略
int a = 1;
doube b = 1;
if(a == b)//浮点型是看精度的 达到精度要求之后后面的就不管了
//后面就很有可能不是0(未知值)
//记住一点:浮点型是不能直接判断相等
我们正确的做法:
if(b - a > -0.00000001 && b - a < 0.00000001)//在精度之内能满足则两者相等
//“&&”表示 与,意为同时都要满足。 “||”表示 或,意为二者或多着只要满足其中一个
练习:
根据上面讲的,打印一下字符串看看
打印字符,打印整数,打印小数!!!
建议我们写代码的时候注意一下格式!
格式很简单:遇到大括号缩进一次(tab),没有遇到顶格写
【知识点4】变量
1、内存命名
在程序运行期间是可以改变它的值,实际上改变的一个内存空间的值
代表这个内存空间的这个名字我们就叫变量
ge:
int a;//在操作系统在内存里面扣出4个连续的字节
//将这四个连续的字节取了一个名字叫a
//后续对于这个内存空间的操作都可以通过这个a
a = 1024;//将1024这个值赋值到a所代表的那个内存空间
a = 2048;//将2048这个值重新赋值到a所代表的那个内存空间
这个a就是变量
2、 变量名:
给一个内存单元取了一个名字,这个名字符合c语言的命名规则就可以了
c语言的命名规则:字母下划线数字,开头只能是字母或者下划线
a123;
_123
_a_123
____123;
123_asd;//不行 数字不能开头
因此我们取名字可以随便取,但是不能乱搞
尽量做到见其名知其意
每天尽量去训练一下自己取名字的能力
3、 变量的定义:
变量的定义只能是:变量类型 变量名;
变量类型:可以是基本类型,也可以是构造类型
变量名:符合c语言的命名规则就可以了
//int a [3] = {....} 可以理解为 int [3] a
变量类型 变量名
对这个变量的访问:只有两种形式
1 读
2 写
读:将变量的值读出来
实际上就是通过这个变量的名字去找到那个存储空间(内存),
然后从这个内存里面取出这个值,根据这个变量的类型去找字节
变量定义出来之后代表的内存空间以及内存空间的大小就不可改变了
写:将一个值写入到这个变量里面去
实际上就是将这个值转换成二进制,然后覆盖a所代表的这个内存空间
int a;
a = 1024;//将1024这个值赋值到a代表的地址
a这个时候代表的是左值,代表了一个可以写的地址
int b;
b = a;//将a里面的值读出来然后赋值给b
a这个时候代表的就是右值,代表了一个可以读的地址
每一个变量都可以代表左值与右值
分别代表了这值得可读与可写
我们在代码里面就可以去这些变量进行操作了
算数运算等等一系列处理
练习:
1 、定义三个变量,对其进行加法运算,然后将值打印出来
2、 char a = -3;
printf("%d\n",a);
printf("%u\n",a); 分别看看等于多少 %u是以无符号的形式打印
unsigned char a = -3;
printf("%d\n",a);
printf("%u\n",a); 分别看看等于多少
代码:
void test03()
{
char a = -3;
printf("%d\n",a);//-3
printf("%u\n",a);//2*32-3
unsigned char b = -3;
printf("%d\n",b);//253
printf("%u\n",b);//253
}
3 char a = 253;
char d;
d = a + 7;
printf("%d\n",a);
printf("%u\n",a);
printf("%d\n",d);
printf("%u\n",d);
代码:
void test05()
{
char a = 253;
char d;
d = a + 7;
printf("%d\n",a);//-3
printf("%u\n",a);//2^32-3
printf("%d\n",d);//4
printf("%u\n",d);//4 尝试了一下,先扩容再相加和先相加再扩容是一样的
}
【知识点5】整形数据:
1、整形数据的存储:整形数据在计算机里面是以二进制的补码形式存储的(重点!!!)
二进制的补码?
补码:
正数的补码 = 原码。
原码就是它的二进制
eg:
假设这个数据是8bit的
13 -> 0000 1101->这个二进制就是13的原码
负数:
负数的补码是他的绝对值的原码,取反+1
假设这个数据是8bit的
-3
3 -> 0000 0011
取反 1111 1100
+1 1111 1101
因此-3的补码就是1111 1101 -> 这个数实际上是一个比较大的正数的原码
253 -> 1111 1101
一个负数与一个较大的正数的存储形式是一样的
char a = -3; -> 1111 1101
printf("%d\n",a);-> %d打印的时候会将后面的这个玩意儿看出是一个int型
转换成一个比较长的应该是有符号的补符号位
1111 1111 1111 1111 1111 1111 1111 1101
-> -3
printf("%u\n",a);-> %u是unsigned int的形式打印
1111 1111 1111 1111 1111 1111 1111 1101
%u不看符号 因此打印的值就是上面的值 直接将2进制转换成10进制即可
2 ^ 32 - 3
2、整数在存储的时候是分为正数与负数的(小重点!!)
正数的表示前面有一个符号位,也就是最前面的那个bit是1表示这个数是负数,如果是0表示是正数
如果是无符号的,那么所有的bit都是数据
3、系统里面的常用的极端值
#include <stdint.h>
INT32_MAX -> 32bit有符号的最大值
INT32_MIN -> 32bit有符号的最小值
UINT32_MAX -> 32bit无符号的最大值
INT32_MIN -> 32bit有符号的最小值(0)
INT16_MAX
INT8_MAX
4、整形数据之间的赋值问题?
char
short
int
他们之间是可以直接赋值的
eg:
int a = 1024;
char c = 23;
c = a;
赋值规则:(重点!!!)
1 长的赋值给短的(不管有没有符号)
低字节直接拷贝,高字节直接不用丢弃即可
int a = 0xabcdef12;
char c;
c = a;
printf("%d\n",c); -> 0x12
代码:
void test10()
{
int a = 0xabcdef12;
char c;
c = a;
printf("%d\n",c);//18
}
2 短的赋值给长的
如果是有符号的,低字节直接拷贝,高字节补齐符号位。符号是0补齐0,符号是1全部补1
如果是无符号的,那么低字节直接拷贝,高字节全部补0
char a = -3;
int b;
b = a;
printf("%d\n",b);
printf("%u\n",b);
代码:
void test11()
{
char a = -3;
int b;
b = a;
printf("%d\n",b);//-3
printf("%u\n",b);//2^32-1
}
void test12()
{
unsigned char a = -3;
int b;
b = a;
printf("%d\n",b);//253
printf("%u\n",b);//253
}
练习:
1 判断下面的输出结果 想一下为什么
char c = 253;
c = c + 7;
printf("%d\n",c);4
printf("%u\n",c);4
unsigned char c = 253;
c = c + 7;
printf("%d\n",c);
printf("%u\n",c);
代码:
void test06()
{
char c = 253;
c = c + 7;
printf("%d\n",c);//4
printf("%u\n",c);//4
unsigned char d = 253;
d = d + 7;
printf("%d\n",d);//4
printf("%u\n",d);//4
}
2 short a = 32767;
short b = a + 2;
printf("%d\n",b);
printf("%u\n",b);
代码:
void test07()
{
short a = 32767;
short b = a + 2;
printf("%d\n",b);//ffff8001
printf("%u\n",b);//ffff8001
printf("%x\n",b);//32769
}
5、上面的代码都牵涉到一个叫溢出的问题(重点!!!)
溢出:实际上也是一个计算出来的结果
实际上就是一个长的赋值给短的过程
char c = 253;//1111 1101 ->-1 1111 1100 ->~ 0000 0011
c = c + 7; //c = -3 + 7 = 4; -> 0000 0100
printf("%d\n",c);4
printf("%u\n",c);4
unsigned char c = 253;//1111 1101
+ 0000 0111
= 1 0000 0100
c = c + 7; -> 253 + 7 = 260 -> 1 0000 0100 //直接将前面的1舍弃即可
printf("%d\n",c);//4
printf("%u\n",c);//4
short a = 32767;//0111 1111 1111 1111
+2 0000 0000 0000 0010
= 1000 0000 0000 0001
short b = a + 2;//b = 1000 0000 0000 0001
printf("%d\n",b);//11111111 11111111 1000 0000 0000 0001
-1 11111111 11111111 1000 0000 0000 0000
~ 00000000 00000000 0111 1111 1111 1111
printf("%u\n",b);//ffff8001
溢出问题就是计算出来的结果,计算出来了溢出了一个直接舍弃不要就可以了
计算机里面的负数为什么要使用补码的形式?
char a = -3;// 1111 1101
char b = 7; // 0000 0111
+ 10000 0100 -> 就是一个溢出1的4
直接舍弃前面的溢出的那个玩意儿就是计算结果
char c = a + b;//7 - 3 = 4
时钟1点钟 + 12 相当于多走一圈 还是回到了1点
实际上已经溢出了1 直接不用这个溢出的1 那么结果一样
24
25 - 1;
25 + 99 = 124; //直接将前面溢出的1不要 就是等于24
因此计算机里面为了省掉不用减法器而实现的这么一套机制
计算机里面的负数都是用补码的形式存在的
总结:
1 变量以及常量
每一个变量都可以有两种意思
1 左值 -> 代表一个可以写的地址
2 右值 -> 代表一个可以读的地址
2 整形数据的一个存放
以补码的形式存在
3 溢出问题,实际上就是长短赋值的问题
--------------------------------------------------------
以下的东西相当于是加给你们的
float -> 32bit/4byte
1bit符号位 + 8bit指数 + 23bit底数
0.625 = 0.625 * 2 ^ 0
1bit符号位: 0
8bit指数: 基数是127
127 + 0 -> 127
0111 1111
0.625:首先前面的都是1 因此我们没有必要将这个1表示出来
计算形式就是*2拿取整数,一直做到为0为止
拿出来的整数依次排开就可以了
10100000000000000000000
0 01111111 10100000000000000000000
double -> 64bit
1bit符号位 + 11bit指数 + 52bit底数