赞
踩
Byte:字节
Word:字,4字节
Half world:半字,2字节
Double World:双字,8字节
type:类型
rollback:回滚:从哪里来回那里去,例如:0,1,2,3,4,5,6,7,8,9
BIN:二进制
OCT:八进制
DEC:十进制
HEX:十六进制
clear
pwd/cd
ls -lh
touch
mkdir -p
rm -fr
cat
cp -fr
mv -fr
echo 配合>,>>
find
frep
whoami
tar
vim三种模式
模式切换
命令行模式的命令
可视模式下的快捷键
文件: 源文件.c 头文件.h 注释: /**/ 可以多行注释,但是不能嵌套 // 可以嵌套,但不能多行注释 主函数main ` int main(void) { //包含一堆得语句; return 0/-1; }
printf
标准C库函数
需要添加stdio.h头文件
printf(“输出信息”); :光标还在本行
printf(“输出信息/n”); : 光标会跑到下一行
占位符: printf("输出信息%d\n", 数字或者变量);
翻译官:把源文件--> 可执行文件
翻译三步骤:
1. 预处理: gcc -E -O XXX.I XXX.C
2. 只编译不链接: gcc -c -o xxx.o xxx.i
3. 链接: gcc -o xxx xxx.o
编译的三种方式:
流氓法,分步法, 一步到位法
内存 字节 Byte 地址 Address 存储区 Buffer 首地址 base address 切记: 1. 只要知道了内存地址,就可以对内存进行读数据 2. 要想访问内存,必须提前分配获取到内存,不能不分配直接访问,否则程序崩溃 问: 如何分配内存呢? 答: 通过定义变量
数据类型 变量名 = 初值;
例如:int a = 250; 此时脑子务必浮现一个内存图
后续可以通过"="给变量赋值(本质就是修改内存里面的数字)
如果不初始化,也就是不给赋值,gcc编译器会给一个随机乱七八糟的数
数据类型的功能:让编译器预算出将来这个变量要分配的内存大小
12类基本数据类型如下:
关键字名称 | 含义 | 分配内存大小 | 包含数字的范围 |
---|---|---|---|
char | 字符类型 | 1字节 | -128~127(背) |
unsigned char | 非负的单字节整数 | 1字节 | 0~255(背) |
short | 双字节整数 | 2字节 | -32768~32767 |
unsigned chort | 非负的双字节整数 | 2字节 | 0~65535 |
int | 四字节整数 | 4字节 | -2^31 ~ 2^31-1 |
unsigned int | 非负四字节整数 | 4字节 | 0~2^32-1 |
long | 四字节整数 | 4字节 | -2^31 ~ 2^31-1 |
unsigned long | 非负四字节整数 | 4字节 | 0~2^32-1 |
long long | 八字节整数 | 8字节 | -2^63 ~ 2^63-1 |
unsigned long long | 非负八字节整数 | 8字节 | 0 ~ 2^64-1 |
float | 单精度浮点数 | 4字节 | 略 |
double | 双精度浮点数 | 8字节 | 略 |
应用:
char a = 1; // 分配1字节的内存
unsigned int a = 1; // 分配2字节的内存
long a = 1; // 分4字节内存
unsigned long long; // 分配8字节
double a = 1.1; // 分配8字节
切记:unsigned int 和 unsigned long对于gcc编译器来说不一样
对于32位系统 / 64位系统,ubsigned int 都是4字节
对于32位系统,unsugned long同样也是4字节
对于64位系统,unsigned long是8字节
将来后续课程讲指针的高级用法,用得着!
每种数据类型都有符号和无符号
有符号的数字有正负之分,无需添加关键字unsigned,但是可以加或者不加signed关键字
例如:
int a = -10; // 等价于 signed int a = -10;
无符号数字(非负)只有0和正数,必须添加unsigned关键字
例如:
unsigned int a = 10;
利用sizeof关键字可以获取变量或者数据类型分配的内存大小
语法:内存大小 = sizeof(变量名或者数据类型关键字名);
例如:
long long a = 1;
printf("%d %d\n", sizeof(a), sizeof(long long));
切记:sizeof圆括号里面如果对变量进行修改赋值操作,此操作是无效的
案例:利用sizeof求变量或者数据类型分配内存大小
实施步骤:
mkdir /tarena/stdc/day03
cd /tarena/stdc/day03
sudo vim sizeof.c
gcc -o sizeof sizeof.c
./sizeof
源代码:
/*sizeof演示*/ #include <stdio.h> int main(void) { char a = 1; unsigned char b = 2; printf("sizeof(a)=%d, sizeof(char)=%d\n", sizeof(a), sizeof(char)); printf("sizeof(b)=%d, sizeof(unsigned char)=%d\n", sizeof(b), sizeof(unsigned char)); short c = 3; unsigned short d = 4; printf("sizeof(c)=%d, sizeof(short)=%d\n", sizeof(c), sizeof(short)); printf("sizeof(d)=%d, sizeof(unsigned short)=%d\n", sizeof(d), sizeof(unsigned short)); int e = 4; unsigned int f = 5; printf("sizeof(e)=%d, sizeof(int)=%d\n", sizeof(e), sizeof(int)); printf("sizeof(f)=%d, sizeof(unsigned int)=%d\n", sizeof(f), sizeof(unsigned int)); long g = 6; unsigned long h = 7; printf("sizeof(g)=%d, sizeof(long)=%d\n", sizeof(g), sizeof(long)); printf("sizeof(h)=%d, sizeof(unsigned long)=%d\n", sizeof(h), sizeof(unsigned long)); long long i = 8; unsigned long long j = 9; printf("sizeof(i)=%d, sizeof(long long)=%d\n", sizeof(i), sizeof(long long)); printf("sizeof(j)=%d, sizeof(unsigned long long)=%d\n", sizeof(j), sizeof(long long)); double k = 10.11; printf("sizeof(k)=%d, sizeof(double)=%d\n", sizeof(k), sizeof(double)); float l = 9.8; printf("sizeof(l)=%d, sizeof(float)=%d\n", sizeof(l), sizeof(float)); int s = 250; sizeof(s = 300); printf("s = %d\n", s); return 0; }
会有报错:原因是系统架构不同的原因,把系统用成32位系统就不会报错了
用单引号括起来表示,其值固定不变,不可修改
例如:
'A', 'a', '1'等
用char或者unsigned char定义的变量,存储的数据本质就是一个字符常量对应的整数
这个整数专业术语叫做ASCII
例如:
char a = 'A'; // 表面上看分配1字节空间,并且里面放了一个字符常量'A'
// 这样理解是错误的
// 本质是分配1字节内存空姐,并且内存里面放了字符常量'A'的ASCII码(就是一个整数而已)
ASCII和字符常量的对应关系:
字符常量 | ASCII码 |
‘A’ | 65 |
‘B’ | 66 |
… | … |
‘a’ | 97 |
‘b’ | 98 |
… | |
‘1’ | 49 |
‘2’ | 50 |
所以:‘d’ - ‘a’ = 本质上是100 - 97 = 3
%c | 按字符常量形式显示 |
%d | 按整数ACSII码形式显示 |
例如:
char a = 'A';
printf("%c, %d\n", a, a); // A,65
案例:演练字符类型(char.c)
/*字符类型演示*/ #include <stdio.h> int main(void) { char a = 'A'; printf("按照字符形式显示%c,按照整数形式ACSII显示:%d\n", a, a); a = 'B'; printf("按照字符形式显示%c,按照整数形式ASCII显示:%d\n", a, a); char b = 'd'; char c = 'a'; printf("b - c = %d\n", b -c); // 实质上是ASCII码相减 char d = 67; printf("按照字符形式显示%c,按照整数形式ASCII显示:%d\n", d, d); unsigned char e = 68; printf("按照字符形式显示%c,按照整数形式ASCII显示:%d\n", e, e); unsigned char f = 'D'; printf("按照字符形式显示%c,按照整数形式ASCII显示:%d\n", f, f); return 0; }
结果:
blue@blue:~/桌面/tarena/stdc/day03$ vim char.c
blue@blue:~/桌面/tarena/stdc/day03$ gcc -o char char.c
blue@blue:~/桌面/tarena/stdc/day03$ ./char
按照字符形式显示A,按照整数形式ACSII显示:65
按照字符形式显示B,按照整数形式ASCII显示:66
b - c = 3
按照字符形式显示C,按照整数形式ASCII显示:67
按照字符形式显示D,按照整数形式ASCII显示:68
按照字符形式显示D,按照整数形式ASCII显示:68
abc
efg'mn"ijk%
‘\n’ | 让光标移动到下一行的行首 |
‘\r’ | 让光标移动到当前行的行首 |
‘\t’ | TAB键 |
‘两个反斜杠’ | 得到一个\ |
‘反斜杠’’ | 得到一个’ |
‘反斜杠"’ | 得到一个" |
‘%%’ | 得到一个% |
案列:利用printf输出以下信息
abc
def\efg'mn"ijk%
答案:
printf("abc\n\t\\efg\'mn\"ijk%%\n");
可以用short,unsigned short, long, unsigned long进行修饰
所以int可以代表两字节或者4字节
id | 形式 | 分配字节数 | 有无符号 | 例子 |
---|---|---|---|---|
形式1 | short (int) | 2 | 有 | short a = 250; 等价于 short int a = 250; |
形式2 | unsigned short (int) | 2 | 无 | unsigned short a = 250; 等价于 unsigned short a = 250; |
形式3 | long (int) | 4 | 有 | long a = 250; 等价于 long int a = 250; |
形式4 | unsigned long (int) | 4 | 无 | unsigned long a = 250; 等价于 unsigned long int a = 250; |
形式5 | int | 4 | 有 | int a = 250; |
形式6 | unsigned int | 4 | 无 | unsigned int a = 250; |
100:gcc编译器默认当成int类型
100L:gcc编译器默认当成long型
100LL:gcc编译器默认当成long long型
100u:gcc编译器默认当unsigned int 类型
100UL:gcc编译器默认当成unsigned long类型
问:虽然类型不一样,但是数值都是常数,有何用
答:这个知识点将来用于数据类型之间的转换使用**
1.23:gcc编译器把它当double类型
1.23f:gcc编译器把他当做float类型
注意:浮点数在计算机中是一个无线趋近的近似值,例如:1.23000001是无限趋近1.23的值
数据类型 | 占位符 |
---|---|
int | %d |
char | %c,%hhd |
unsignde char | %c,%hhu |
short | %hd |
unsigned short | %hu |
unsigned int | %u |
long | %ld |
unsigned long | %lu |
long long | %lld |
unsigned long long | %lld |
float | %f或者%g |
double | %lf或者%lg |
注意:float保留多余的0,double不保留
例如:2.3—>%f/%lf------>2.300000
2.3—>%lf/%lg------>2.3
/*数据类型和占位符演示*/ #include <stdio.h> int main(void) { char a = 97; unsigned char b = 'A'; printf("%c, %hhd\n", a, a); printf("%c, %hhu\n", b, b); short c = 250; unsigned short d = 251; printf("%hd, %hu\n", c, d); int e = 520; unsigned int f = 521; printf("%d,%u\n", e, f); long m = 2345; unsigned long n = 2346; printf("%ld,%lu\n", m, n); long long x = 123456; unsigned long long y = 1234567; printf("%lld,%llu\n", x, y); float s = 23.4; printf("%f\n", s); printf("%g\n", s); double k = 23.4; printf("%lf\n", k); printf("%lg\n", k); return 0; }
结果:
blue@blue:~/桌面/tarena/stdc/day03$ ./type
a, 97
A, 65
250, 251
520,521
2345,2346
123456,1234567
23.400000
23.4
23.400000
23.4
/*回滚现象*/ #include <stdio.h> int main(void) { // char:-128-127 printf("%hhd\n", 127); printf("%hd\n", -128); printf("%hd\n", 127); // 回滚到 127 printf("%hd\n", 129); // 回滚到 129 printf("%hhd\n", 255);// 回滚到 -1 printf("%d\n", 256); // 正常,不会回滚 // unsigned char:0-255 printf("%hhu\n", 255); printf("%hhu\n", 256); //回滚到0 printf("%d\n", 256); // 正常,不会回滚 return 0; }
结果:
blue@blue:~/桌面/tarena/stdc/day03$ vim type2.c
blue@blue:~/桌面/tarena/stdc/day03$ gcc -o type2 type2.c
blue@blue:~/桌面/tarena/stdc/day03$ ./type2
127
-128
127
129
-1
256
255
0
256
计算机数字都是在内存中存储的,,并且这些数字都是以二进制的形式存在
计算机软件中数字的表现形式(展现形式)有四种:
二进制表示,八进制表示,十进制表示,十六进制表示
注意:不管是那种形式都是对同一个内存中存出得数字的不同表示形式而已
内存中的数字不会因为表示绍兴市不一样,数字就发生改变
也就是内存中的数字不会随着进制的改变而改变,内存都是二进制形式!
类比:
人(数字)
在学校(八进制)
在公司(十进制)
在超市(十六进制)
不管在哪里,人本身是不变的!!!
八进制,十进制,十六进制给程序员看的
二进制给计算机看,计算机只认二进制
计算机把内存中每个字节又分8段,没段只能记住0和1
要想把一个数字存储到内存中,必须将这个数字分拆成若干个0和1存储到每个段中
每段对应的专业术语叫:位,bit,bit位
所以,内存的最小存储单元是为(bit)
结论:1Byte = 8bit
2Byte = 16bit
例如:
char a = 'A'; // 分配1字节内存空间,把字符ASCII码分拆成8位(8个0和1)存储到内存中
short a = 250; // 分配2个字节内存空间,把259分拆成16个0和1(需要16位)存储到内存中即可
int a = 250; // 分配4字节内存空间,把250分拆成32个0和1(需要32位)存储到内存中
1.定义:
用一组表示数字的方法简称二进制表示形式
例如:
现在有一个十进制数85(前提是char类型),要存储到内存中,必须以二进制的形式存储
所以需要将85拆分成8个0和1,最终其二进制表示形式位:01010101(二进制形式)
2.特点:
1)二进制数编号:从0开始
例如:前提是char类型
高位 地位
76543210 二进制数的编号
01010101 二进制数
2)二进制中每个1单独代表一个10进制数字,这个十进制数值是2的编号次方
例如:前提是char类型
高位 低位
76543210 二进制编号
01000000 二进制数(其中第六位的1对应十进制数字值是26次方=64)
3)二进制数中相邻的二个1,左边是右边的2倍
4)二进制数加1的时候把编号为0位置开始的多个连续的1变0,最左边的0变1(逢二进一)
例如:
76543210 二进制编号
00001111 + 1 = 00010000
00001110 + 1 = 00001111
问:10进制数85对应2进制凭什么是01010101?
二进制数01010101对应的10进制数为什么是85?
计算机只认二进制,内存中只能存储数字的二进制形式
至于十进制,8进制,16进制都是对内存中二进制数的另外三种表示形式而已
二进制表示的非负数(0和正数)转换成10进制就是把每个二进制中的1单独转换成10进制然后相加
得到最终十进制的值
例如:前提是char类型
76543210 编号
01010101 二进制数A(非负)
A对应的十进制数= 2的6次方 + 2的4次方 + 2的2次方 + 2的0次方 = 64+16+4+1 = 85
结论:
将来存储85就是将85分拆成8个0和1即:01010101,存储到1字节的内存空间即可
***小数点前或者整数要从右到左用二进制的每个数去乘以2的相应次方并递增,小数点后则是从左往右乘以二的相应负 次方并递减。***
1101.01(2)=1x20+0x21+1x22+1x23 +0x2-1+1*2-2=1+0+4+8+0+0.25=13.25(10)
所以总结起来通用公式为:
abcd.efg(2)=d20+c21+b22+a23+e2-1+f2-2+g*2-3(10)
十进制整数转换为二进制整数十进制整数转换为二进制整数采用"除2取余,逆序排列"法。
具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,
如此进行,直到商为小于1时为止,然后把先得到的余数作为二进制数的低位有效位,
后得到的余数作为二进制数的高位有效位,依次排列起来
例如:91这个10进制数转2进制过程
91/2 = 45 余1
45/2 = 22 余1
22/2 = 11 余0
11/2 = 5 余1
5/2 = 2 余1
2/2 = 1 余0
1/2 = 0 余1
结果进制数为:01011011(高位补0,凑够1字节)
85–>01010101
255–>11111111
789–>0000001100010101(前提是short类型,789用char和
unsigned char无法表示,太大了
因为short类型,16位,高出的6位,补0,凑够16位)
负数的十进制和二进制数不能直接转换,必须借助相反数
首先计算相反数,变成整数
然后将相反数转成2进制
最后去反加1得到十进制负数的二进制(取反的意思是1变0,0变1)
例如: 求-14(前提是10进制负数并且数据类型是char)的二进制
1. 计算-14的相反数是14
2. 将14转换成二进制:00001110
3. 取反加1:11110001 + 1 = 11110010
结果:-14的2进制为11110010
有符号类型的数字(不加unsigned关键字修饰)的才能有符号
二进制数中最左边的位叫符号位,通过此为可以确定数字的符号(正还是负,认为自己判断添加符号)
符号位的值为0表示数字为非负数(0和正数),符号位的值为1表示此数字为负数
切记:讨论符号位的前提是必须确定那个数据类型
例如:01010101(前提是char类型),此数对应的十进制必然是正数
10101000(前提是char类型),此书必然是负数
注意:10101000(前提是unsigned char类型),此数没有必要讨论正负,因为加了unsigned说明就是非负数
10001000(前提是short类型),此数必然是正数,因为short类型16位,显然高8位都是0,符号位也为0
1000010110001000(前提是short类型),此数必然是负数
0000111110010000(前提是char类型),此数必然是负数,因为虽然是16位,但是char类型只能要8位
所以从低位开始要8位即可,最后二进制是10010000,此时最高位为1,表示负数
有了这个明确,现在就可以实现二进制表示的负数转10进制
例如:求二进制数10110110的十进制(前提是char类型,显然是负数)
1. 先取反加加1:01001001 + 1 = 01001010
2. 然后将二进制转换10进制:01001010=0x20+0x21+···+1x26+0x27=74
3. 前提是已知这个二进制为负数,所以最后求相反数:-74
结论:10110110的十进制数是-74
1. 先取反加1: 01010101 + 1 = 01010110
2. 将二进制转换成10进制:86
3. 这个二进制为负数,所以求得相反数:-86
1. short类型是16位,因此,此二进制应该是:0000000010101010,是正数
2. 结果是:170
就是把二进制数从右到左边每3位分为一组
每组用一个0到7的数字替换得到8进制表示形式
注意:八进制数前加0来表示,例如:0250(书名这个数是一个八进制数)
占位符:0%o
**例如:**二进制数0110 1001(十进制是105)转成八进制,三步骤
1. 先分组: 01 101 001
2. 换算(二进制转十进制算法):
01 = 1x2^0 + 0x2^1 = 1
101 = 1x2^0 + 0x2^1 + 1x2^2 = 5
001 = 1x2^0=1
3. 替换得到:0151
1 /*进制转换*/
2 #include <stdio.h>
3
4 int main(void)
5 {
6 int a = 105; // 10进制
7 printf("a的十进制数是:%d, a的八进制数是:0%o\n", a, a);
8 return 0;
9 }
鄙视用计算器,务必要口算,核心内容,核心中的核心
把二进制数从右边到左边每4位分为一组
每组用一个字符替换(用a到f之间的字符替换10~15之间的数字)
注意:16进制数前面需要添加0x或者0X,不区分大小写
占位符:%#x 或者%#X
例如:11000011转换为16进制,分三步
1. 先分组(四个一组): 1100 0011
2. 换算:
1100 = 22+23 = 4 + 8 = 12
0011 = 2^0 + 2 ^1 = 1 + 2 = 3
3. 替换
12 --> c
3 —> 3
4. 结果:此二进制对应的16进制为:0xc3或者0XC3或者0xC3或者0Xc3
务必拿下二进制和16进制的转换口算
在程序中一般用16进制来表示二进制,16进制也就是二进制
16进制 | 2进制 |
---|---|
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 |
高位 | 低位 | |
---|---|---|
0x48 | 0100 | 1000 |
0xb6 | 1011 | 0110 |
0xfac7621d 1111 1010 1100 0111 0110 0010 0001 1101
0xa596ef1 1010 0101 1001 0110 1110 1111 0001
问题:例如这个16进制数0xa596ef1【四字节数据】在内存中如何存储呢?如何排兵布阵呢?
答:具体参见内存操作示意图
分析:
由于内存的每个字节只能存8位,所以将0xa596bef1这个数据分成4个字节,每个字节8位
分别是:0xa5, 0x96, 0xbe, 0xf1
问:250(数据类型为int类型)这个10进制数在内存中如何存储?
250->0x000000FA->0000 0000 0000 0000 0000 0000 1111 0101->4字节内存
问:-250如何存?
-250->0xFFFFFF06->1111 1111 1111 1111 1111 1111 0000 0110->四字节内存
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。