Missing Semester 与 现代 C++ 笔记
基础知识
- 需要对 C 语言和面向对象有基本的了解
- 需要对 Linux Shell 有基本的了解
- 自测: 请回答以下几组问题并阅读以下几组代码
int 和 float 的计算机实现是什么?
float Q_rsqrt( float x ) {
union {
float f; uint32_t i; } y;
float x2 = x * 0.5F;
y.f = x;
y.i = 0x5f3759df - ( y.i >> 1 );
y.f = y.f * ( 1.5F - ( x2 * y.f * y.f ) );
// y.f = y.f * ( 1.5F - ( x2 * y.f * y.f ) );
return y.f;
}
类型转换
int i = 1;
char* pc = (char*)(&i);
if(pc[0] == '\x1') {
puts("This system is little-endian");
} else {
puts("This system is big-endian");
}
大括号与作用域
int main() {
int i = 0;
for ( ; i < ({
int r = rand();
printf("r == %d\n", r);
(r + i)%10;
}) ; i++ ); // gcc
printf("i == %d\n", i);
return 0;
}
指针与地址 (现代 C++ 中, 应该使用 using)
T *p; p = &o; p = (T *) malloc(size);
T0 *p(T1, T2); p = ( T0 (*)(T1, T2) ) pf;
const T *p; T * const p;
int n; int * const np = &n; int *const *npp = &np;
// 指向指向 非const 的 int 的 const 指针的 非 const 指针
int (*(*foo)(double))[3] = NULL;
assert(foo == NULL);
foo = ( int (*(*)(double))[3] ) fp;
int bar = (*(*foo)(1.2))[1];
void (*signal(int sig, void (*func)(int)))(int);
// a better way
typedef void (*sighandler_t)(int);
sighandler_t signal(int, sighandler_t);
#include <stdio.h>
int main()
{
int (*fp)(void) = &main;
// int (*fp)(void) = main;
// int (*fp)(void) = *main;
int (**fpp)(void) = &fp;
printf("fp == %p\n", fp);
printf("&fp == %p\n", &fp);
printf("&fpp == %p\n", &fpp);
return 0;
}
// fp == 0x401122 // main .text
// &fp == 0x7ffddaf5d8b8 // fp stack
// &fpp == 0x7ffddaf5d8b0 // fpp stack
// 函数调用也是运算符, 联系到函数调用的汇编实现, 一切就说的通了
// 在编译器眼中, &func == func
// file1.c
char s[64] = "Hello World!\n";
// file2.c
extern char *s;
int main() {
printf("%p\n", s); // 防止 s 被优化掉
// printf("%c\n", s[0]; // Segmentation fault
return 0;
}
// extern 既非强符号,也非弱符号。
// 无法匹配相同类型强符号之后就归入.bss节。
// gcc file1.c file2.c
// xxd a.out 会发现 "Hello World!\n" 位于 .rodata 节
动态分配内存
volatile 变量是什么意思? 原子变量是什么意思?
echo hello world
的执行过程?
- 文件系统如何通过 inode 管理? 目录项 (路径) 和 inode 的关系?
- shell 的文件操作
pwd
,cd
(本质上是 shell 的函数, 而不是一个可执行的二进制文件, 至少在 Linux 上如此)ls
cp
,mv
,rm
,ln
,ln -s
mkdir
,rmdir
(empty only)touch
find
-type
(d
,f
)-name
-mtime
-size -4k -size +4G
-exec rm {} \;
chmod
,chown
,ls -l
- 其他磁盘驱动有关的命令
df
与du
(estimate) 的区别?cat
(head
,tail
,tee
) 与dd
(DataDef) 的区别? (dd
可以调用 seek)- 重定向
>
,<
(>>
,1>
,2>
,&>
)
<<
指定长文档的结束符<<<
指定长字符串- 以上两种用法等同于stdin重定向为输入的长文档/长字符串
nc
(NetCat) 与curl
(pup
jq
) 的区别? (curl
面向 HTTP)echo
与printf
的区别?echo str
,echo "str"
,echo 'str'
- 桌面环境 (KDE plasma) 中程序的运行实际上也是 一个特殊的 shell 的子进程, 利用
pstree
命令可以观察到 plasmashell 的子进程有 code, netease, chrome.
- 解释器提取 3 个 token, 依次是
echo
,hello
,world
. - (不是布尔表达式; 没有管道;) 第一个 token, 也仅有这个 token, 指示一个可执行的二进制文件. 通过查找环境变量 (
echo $PATH
) 获得这个可执行目标文件的绝对路径 (实际上是which echo
之一). - 之后的 2 个 token 是参数列表.
- 执行 exec 库函数, 传入绝对路径和参数列表.
- fork Shell 进程, 替换镜像, 高地址压入环境变量, 低地