total-编程知识点集锦
# 文章
https://www.163.com/dy/article/GF8RI6NE0552D3ZX.html
# TopK
# 用两个栈实现一个队列
# stl中哪个容器遍历最快?
vector,因为内存连续,cache命中率高
# mysql优化
# inline的特点
# socket epoll 和select
# atomic底层实现
总线锁
# 哪些资源是线程独有的
std::thread_local相关
线程共享:进程代码段、进程的公有数据、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID; 线程私有:线程ID、寄存器里的值、栈、线程的私有数据、线程的优先级、信号屏蔽码、错误返回码。
# 大端小端大小端
https://blog.csdn.net/qq_41016462/article/details/88537650 (opens new window)
大端是人思维的字节序,正常从左到右,地址从小到大。
小端存储是整体按字节从右向左看,但是每个字节内部是不变的。
对于结构体来说,小端是整个结构体按字节从右向左,第一个成员在最右端。
#include<stdio.h>
#include<stdio.h>
int main(){
typedef unsigned int uint16_t;
struct myst
{
uint16_t a:3;
uint16_t b : 8;
uint16_t c : 5;
};
struct myst *p;
int t = 0x2041;
p = ((struct myst *)&t);
printf("%d", p->c);
system("pause");
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
0x2041在大端中内存为
0010 0000 0100 0001
(从左到右,低地址->高地址,每个bit内部也是低->高) 所以在大端中a为001 b为00000010 c为000010x2041在小端中的内存为
1000 0010 0000 0100
(从左到右,低地址->高地址,每个bit内部也是低->高) 按字节从右向左,跟大端刚好完全相反 所以在小端中a为前 3 bit 100, b为接下来8bit 00010000, c为 00100不论大端小端,p->a 都等于3, p->b都等于8 p->c都等于5, 也就是说大小端位域的用法在自身机器上都是自洽的,可以正常使用 对于左移,不论大小端,都是往最高字节移,不溢出的情况下,左移1位都相当于乘以2,也就是说位移运算也是自洽的。
小端机器上:
printf(%d\n, htons(6))
, 输出为1536。 将6从小端转为网络字节序,6在小端内存中为0x06 0x00
, 二进制为0000 0000 0000 0110
, 转成网络字节序并不是连同字节内部也转成大端,而是以字节为单位逆序,字节内部是不变的,也就是转换为0x00 0x06
, 二进制为0000 0110 0000 0000
,十进制为1536。
# 堆排序
https://www.jianshu.com/p/21bef3fc3030
# 读写锁
具体实现
# 字节对齐的好处
不同cpu的结构不一样,不对齐的话可能会出现数据不一致;
提高cpu读取效率:比如有些平台CPU从内存中偶数地址开始读取数据,如果数据起始地址正好为偶数,则1个读取周期就可以读出一个int类型的值,而如果数据其实地址为奇数,那我们就需要2个读取周期读出数据,并对高地址和低地址进行拼凑,这在读取效率上显然已经落后了很多了。
# 位运算
# 算术右移和逻辑右移
参考: https://blog.csdn.net/weixin_44509533/article/details/109080809 (opens new window)
左移比较简单,算术左移和逻辑左移一样都是右边补0
右移包括算术右移和逻辑右移
- 逻辑右移很简单,只要将二进制数整体右移,左边补0即可
- 算术右移符号位要一起移动,并且在左边补上符号位,也就是如果符号位是1就补1符号位是0就补0
- c语言中有符号类型右移时用算术右移; 无符号数移位时用逻辑右移。(不同机器可能不同) 也就是说,不管有无符号,右移后都减半。
移动位数超出32或64时取余数或置零等(取决于编译器):
取余的情况:在移位运算时,byte、short和char类型移位后的结果会变成int类型,对于byte、short、char和int进行移位时,编译器实际移动的次数是移动次数是32的余数,也就是移位33次和移位1次得到的结果相同。移动64位时,实际移动64的余数,也就是移动66次和移动2次得到的结果相同。
其他情况:编译器不一定会取余,也可能使移位结果变为0,或者做其他处理,取决于编译器。
# 位运算示例
有时位运算可以避免使用if,从而降低 cpu pipeline 分支预测错误带来的开销。
n字节对齐,把a按n(2的整数次方)对齐的位运算为:
(a + n - 1) & (~(n - 1))
// 即如果 qn < a <=(q+1)n, 则把a对齐到(q+1)n。
//align should be power of 2, like 1024
#define ALIGN_UP(value, align) (((value) + ((align) - 1u)) & ~((align) - 1u))
#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1u))
2
3
4
5
6
# delete和delete[]
参考: https://blog.csdn.net/u012936940/article/details/80919880 (opens new window)
唯一区别: 对于自定义数据类型,delete [] 可以逐个调用析构函数,而delete只会调用一个。
# 构造函数和析构函数中调用虚函数
可以调,但是调了不会呈现出多态
# 匿名联合体和匿名结构体
https://blog.csdn.net/openblog/article/details/7548363 (opens new window)