【C++学习】一些笔记(01)格式化输入和输出 浮点数 位运算


前言

学习的一些笔记,有必要的才记,没必要的就不记了


一、概述

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. 输入输出模型

  1. 核心矛盾:CPU内部、内存和I/O设备处理数据的速度存在很大的差异。
  2. CPU和内存之间:高速缓存、TLB、编译器优化…
  3. 内存和I/O之间:缓冲区(buffer)、缓存(cache/ Redis)…
  4. CPU和I/O之间:DMA.
  5. 转换说明的格式: %m.pX(右对齐), %-m.pX(左对齐)
    X: 以什么方式解释这个内存空间
    m:最小字段宽度
    p:精度
  6. printf的返回值:显示字符的个数。
  7. scanf对于其他字符时精准匹配,但可以匹配任意个空白字符。
    scanf的返回值:成功匹配的转换说明的个数。
  8. 程序员可以通过添加后缀来指定整数字面值的类型:
    43U:无符号整数
    43L:long型整数
    43LL:long long 型整数
  9. 转换说明:
    %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. 字符编码

  1. ASCII码:
    ‘\0’ = 0,
    ’ ’ = 32,
    ‘0’ = 48,
    ‘A’ = 65,
    ‘a’ = 97

  2. 字符分类函数:
    字符分类函数

  3. 字符操作:
    ① tolower():转换成小写
    ② toupper():转换成大写

  4. 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;

总结

主要是位运算重要一点,其他的还行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值