硬盘.内存条.CPU.CPU寄存器.缓存图片,CPU缓存为寄存器和内存之间
汇编的一些初级demo
关键字:
数据类型:告诉编译器需要多大的空间存储这个数据
extern是一个关键字,声明一个变量,但是没有存储空间
不能直接赋值
二进制的名称,左边是高位,右边是低位
进制存储的一些知识
十进制小数转化成小数的方法
八进制和二进制相互转化,从右往左边分三位
二进制和十六进制则是一个十六进制位对应4个二进制位
八进制和十六进制则是通过二进制进行互转
原码,反码,补码知识:
原码(用户角度),原始的二进制
- 用户的数字分为正负数,符号位的存储
- 最高位为符号位,0为正数,1为负数
- 1000 00001 左边是高位,右边是低位
+1 0000 0001
-1 1000 0001
0 0000 0000
-0 1000 0000
原码存储数据有两个问题
1.0有两种存储方式
- 正数和负数相加,结果不正确(计算机只会加不会减)
- = 1+(-1)
1:0000 0001
-1:1000 0001
= 1000 0010(!不对)
反码(为了算补码):
- 正数的原码和反码一样
- 求原码
- 在原码基础上符号位不变,其他位数取反(0 1 互换)
+1 0000 0001
-1 1 111 1110
0 0000 0000
-0 1111 1111
反码仍然存在一个问题:
0 有两种存储方式
-
- =
1 + (-1)=
0000 0001
1111 1110
=
1111 1111
= -0
补码的方式存储(为了解决负数的存储)
补码:正数的原码 反码 补码都是一样的
负数的补码:反码加一
+1: 0000 0001
-1: 1111 1111
+0: 0000 0000
-0: (1) 0000 0000 (最高位丢弃,1去掉,只剩下八个0)
以补码计算:
1 + (-1)
=
0000 0001
1111 1111
0000 0000 = 0 最高位丢弃
补码的特点:
- 正数,原码 反码 补码都相同
- 对于负数, 反码加1
- 补码符号位不变 其他位数求反,加1得到原码
十进制数:站在用户的角度,原码
二进制.八进制.十六进制数,站在计算机的角度,补码
一个字节,八位
二进制1000 0001
十六进制 0x81
补码和反码的互相变化是一样的
%d默认是以有符号的数来打印
有符号和无符号的区别:
- 有符号,最高位是符号位,如果是1代表为负数,如果是0代表为正数
- 无符号,最高位不是符号位,是数的一部分,无符号不可能是负数
打印一个数的时候,如果是指定有符号,那么最高位就当成符号位,无符号,有符号就是一个数字
数据类型范围:
char 1个字节
有符号的范围
正数0000 0000 - 0111 1111 127
负数-0 - 1111 1111 -0当成一个-0
-128
原码:1 1000 0000
反码:1 0111 1111
补码:1 1000 0000
这是一个边缘值
数值越界:复制和运算,记得不要越界
char ch = 127 + 2;
0111 1111
0000 0010
1000 0001
1111 1110
+1111 1111
-127
输出格式的总结:
%d 十进制
%o 八进制的int
%x 十六进制,小写
%X 十六进制,大写
%u 输出一个十进制的无符号数字
%hd short型
%l long
%ll long long
%hu unsigned short
%lu unsigned long
%llu unsigned long long
数字后面加后缀
10l 10 ll 10ul
内存里面没有字符,只有数字,一个数字对应一个字符,ascii码,怎么查看,linux man ascaii
字符:原则上之后又一个字符,但是转义字符除外
转义字符,由\前缀的字符,常用的:
ch = ‘\r’;//句首
printf("\x42\n");
这么用:将一个十六进制表示的字符填充进去
float double浮点型
float 四个字节
double 八个字节
类型限定符
register:
volatile:
比如
随着a的值变化,各种灯就会变化;
a=1;
a=2;
a=3;
a=4;
如果优化了,就会让a直接等于4;
不优化,就逐个进行赋值
打印相关
putchar 将字符输出到标准输入
getchar 从标准输入读取字符
scanf的使用
用户输入字符的时候,将输入放入到内容里面,scanf自动在缓冲区中读完内容.
例如:输入a回车,
缓冲区写入a \n ,scanf并退出,下一次的scanf会读取\n,因此连续两次输入scanf,中间加一个scanf吃掉一个回车符\n
两个数相除,保证一个数是一个小数,才能得到一个小数,不然就会取整数
前置后置++,前置,操作前(包括赋值)++,后置,操作后(包括赋值)++,
真假的短路规则:
|| 左边为真,右边不执行
&& 左边为假,右边不执行
隐式转换,显示转换:
强制转换,小的往大的转
低地址,指针开始指向的地方,高地址,指针走向,
大小端:大端:数据的低字节序放在高地址,高字节序放在低地址如 char 2 :
0000 0010
大端:指针从左边开始指向,先操作符号位,然后往下,
大小端各有好处,大端对于符号的处理快,小端对于数据的加减运算快
goto只能到同一个作用域
不初始化的数组值是随机数
二维数组在内存里面的存储是一维数组,
二维数组的传参问题,将传参 char ** 等于 char *argv[]
传参要用char* a[] 初始化,不要定义char[3][4]这种,这种是一维数组,会出问题
// \0 后面不跟数字,有可能组成转义字符
常用的数组初始化:char a[10] = =”abc”;
随机数生成,配合系统时间使用
time(NULL)
scanf 不对越界检查,对空格敏感
gets 允许空格存在
fgets 安全,因为有一个长度输入,如果是键盘输入,就使用stdin,会把换行符号读进去
字符串输出:
puts自动加上一个回车换行
fputs 不会加上回车换行
字符串长度:strlen不会把\0计算在内,其他的会计算,比如\n
strcpy 和 strncpy 遇到\0就不会再拷贝后面的内容了,这种情况只能靠memcpy
这种函数很容易出现段错误 strcpy
字符串的比较逐个比较ascii码
sscanf 从str指定的字符串,读取数据,并根据参数format字符串转换并格式化数据
char src[] = “a=10, b=20”;
int a;
int b;
sscanf(src, “a=%d, b=%d”,&a,&b);
printf(“a:%d, b:%d\n”,a,b);
字符串的切割:strtok