文章目录
前言
学习的一些笔记,有必要的才记,没必要的就不记了
一、概述
1. 多字节数据如何存储:
如:0x 00 00 00 FF
① **大端表示法**:高地址存放在低有效位。
地址:
低 -------->高
00 00 00 FF
② **小端表示法**:高地址存放在低有效位。
地址:
低 -------->高
00 00 00 FF
2. 16进制一些记忆点:
16进制:A B C D E F
10机制:10 11 12 13 14 15
3. 程序是如何生成的:
二、格式化输入输出
1.进程虚拟内存
代码如下(示例):
2. 常量
#define N 5 //在预处理阶段文本替换成5
const int M =5 //M对应一块不可写的内存空间,运行阶段才知道M的大小
3. 输入输出模型
- 核心矛盾:CPU内部、内存和I/O设备处理数据的速度存在很大的差异。
- CPU和内存之间:高速缓存、TLB、编译器优化…
- 内存和I/O之间:缓冲区(buffer)、缓存(cache/ Redis)…
- CPU和I/O之间:DMA.
- 转换说明的格式: %m.pX(右对齐), %-m.pX(左对齐)
X: 以什么方式解释这个内存空间
m:最小字段宽度
p:精度 - printf的返回值:显示字符的个数。
- scanf对于其他字符时精准匹配,但可以匹配任意个空白字符。
scanf的返回值:成功匹配的转换说明的个数。 - 程序员可以通过添加后缀来指定整数字面值的类型:
43U:无符号整数
43L:long型整数
43LL:long long 型整数 - 转换说明:
%d:十进制有符号整数
%u:十进制无符号整数
%o:无符号八进制整数
%x:无符号十六进制整数
读写short,前加h,%hd
读写long,前加l,%ld
读写longlong,前加ll,%lld
三、数据类型
1. 浮点数
编码(IEEE754标准):
这篇文章写的很好:
IEEE754详解(最详细简单有趣味的介绍)
这边贴一个我自己写的解释:
32位内存编号从高到低(31到0),一共包含:
sign符号位:占1位(31)
biased exponent偏移后的指数位:占8位(30-23)
fraction尾数位:占23位(22-0)
① 符号位:用于表示这个浮点数是正数(0)还是负数(1)
②规范化: 将十进制的浮点数表示为二进制格式,并规范化即转换为以2为底的指数形式,如:10100.1 = 1.01001 * 2^4,需要把小数点放在左起第一位和第二位之间. 且第一位需要是个非0数。
偏移后的指数位:这里的4是偏移前的指数,为了让指数位均为正数便于存储,需要加上偏移量。32位单精度浮点数的偏移量(bias)为127,偏移后指数(就是 4 + 127 = 131, 131转换为二进制就是1000 0011。
尾数位:1.01001就是尾数,但还需要对尾数进行隐藏高位1和低位补0的处理。则尾数位:0100 1000 0000 0000 000 (补至23位)。
③ 综上所述:
十进制浮点数 20.5 的:
符号位是: 0
偏移后指数位是: 1000 0011
补零后尾数位是: 0100 1000 0000 0000 000
在32位浮点数容器中, 则为 0 1000 0011 0100 1000 0000 0000 000
2. 字符编码
-
ASCII码:
‘\0’ = 0,
’ ’ = 32,
‘0’ = 48,
‘A’ = 65,
‘a’ = 97 -
字符分类函数:
-
字符操作:
① tolower():转换成小写
② toupper():转换成大写 -
getchar() 和 putchar():
常用:读取某一行剩余字符:
while (getchar()!='\n'){} //包括换行符
3. 类型转换
1. 隐式类型转换
2. 显式类型转换
① 计算浮点数的小数部分
double d=3.14;
double fraction =d-(int)d;
② 提高代码可读性
float f=3.14f;
③ 对类型转换进行更精确的控制
int divided=4,divisor=3;
double quotient;
quotient =(double)divided/divisor;
④ 可以避免溢出
long long milliSeconds = 24 * 6e * 68* 1000;
long long nanoSeconds = (long long)24 * 60 * 60 * 1000 * 1000 * 1000;
printf("nanoSeconds / milliSeconds = %lld \n", nanoSeconds / milliSeconds);
4. typedef 起别名
数据结构中经常见:
① 能够提高可迁移性
② 提高代码可读性
四、表达式
1. 算术运算符
1. 加减乘除模的注意事项
① + - * / 可以用于浮点数,%不能用于浮点数;
② 两个整数相除,其结果为整数(向下取整;
③ i%j的结果可能为负,符号与i相同;
④ 不能模2等于1这样判断一个整数是否为奇数,因为如果n为负奇数的话,模2计算得到的值为-1。
//判断一个整数是否为奇数
//第一种做法是错误的
bool isOdd(int n){
return n%2==1;
//第二种做法是正确的
bool isOdd(int n){
return n%2!=0;
//第三种做法是正确的
bool isOdd(int n){
//和1相与,因为如果是奇数,二进制低位一定是1
return n & 0x1;
2. 运算符
① 注意几个没见过的:
>> 右移
<< 左移
>>= 右移赋值
<<= 左移赋值
② 关系运算符
有一个短路原则:
指如果在进行前面的表达式的运算过程,通过判断已经明确的知道整个表达式的结果,那么就不会进行后面表达式的运算判断。
if(i != 0 && j / i > 2){
....
}
五、位运算
虽然它也是在表达式的知识点之一,但是由于它很重要,就单独列出来。
1. 位运算符
>> 右移
<< 左移
~ 按位取反
& 按位相与
| 按位相或
^ 按位异或
>>= 右移赋值
<<= 左移赋值
2. 移位运算符
1. i << j: i左移j位,右边补0
若没有发生溢出,左移j位,相当于 x 2^j
2. i >>j: i右移j为,右边补0
若没有发生溢出,左移j位,相当于 x 2^-j(向下取整)
为了代码的可移植性,不要对有符号整数进行移位。
**注意:**移位运算时,操作数会先取余,然后再移位。
3. 性质:
这个是很重要的,因为后面的位运算题能用到。
a ^ 0 = a;
a ^ a = 0;
a ^ b = b ^ a;
(a ^ b) ^ c = a ^ (b ^ c);
4. 一些面试题
① 交换
m ^ k = c;
m = c ^ m;
k = k ^ m;
② 如何判断一个数是否为奇数
bool isOdd(int n){
return n & 0x1;
}
③ 如何判断一个整数是否为2的幂?
第一种:
bool isPowerOf2(unsigned n){
unsigned i = 1;
while(i < n){
i <<= 1;
}
return i == n;
}
第二种:
2的幂二进制表示形式,只有1位为1,其余位为0。
bool isPowerOf2(unsigned n){
return (n & n - 1) == 0;
}
④ 给定一个不为0的整数,找出lastSetBit
输入:0011 0100
输出:4
(补码运算)
int lastSetBit(int n){
return n & -n;
}
⑤ 给定一个数组,里面的整数都是成双成对出现的,只有一个数例外,请找出来。
输入:[1,1,2,2,3,3,4,4,5]
输出:5
void find_single_nums(int arr[], int n) {
int singleNum = 0;
for (int i = 0; i < n; i++) {
singleNum ^= arr[i];
}
return singleNum;
}
⑥ 给定一个数组,里面的整数都是成双成对出现的,只有两个数例外,请找出来。
输入:[1,1,2,2,3,3,4,4,5,6]
输出:5,6
(分类的思想,xor = a^b,找出lastSetBit,和这位相与为0的分为一类,相与为1的分为一类)
void find_single_nums(int arr[], int n, int* a, int* b) {
int xor = 0;
for (int i = 0; i < n; i++) {
xor ^= arr[i];
}
// xor = a ^ b;
// find xor variable's last set bit.
int lastSetBit = xor & (-xor);
*a = 0;
*b = 0;
for (int i = 0; i < n; i++) {
if (arr[i] & lastSetBit) { // lastSetBit设置的为一类
*a ^= arr[i];
} else { // lastSetBit未设置的为一类
*b ^= arr[i];
}
}
}
⑦ 求一个数的二进制数中有多少1
输入:2
输出:1
(补码运算)
int count = 0;
int flag = i;
while (flag > 0) {
if ((flag & 1) != 0) count++;
flag = flag >> 1;
}
p[i] = count;
总结
主要是位运算重要一点,其他的还行。