1 入口点 (Entry Point) 和 程序初始化
程序入口 真的是 main 函数吗 ? 不是
(1) 程序运行步骤
1) OS 创建 进程 -> 控制权转交 给 `入口点: 运行库` 中 `某个入口函数`
2) 入口点 对 运行库 和 程序运行环境 `初始化`
[1] globalVar 构造
[2] 堆
可放心 malloc/new
[3] 栈
环境变量 / argv / argc 入栈
main 的 2 个 para (argc / argv) 被正确传了进来
[4] I/O
可放心用 scanf/printf
[5] 线程
3) 调用 main
4) 记录 main 的 returnValue
-> `反向清理` -> 系统调用 `结束进程`
(2) 入口函数 如何实现?
Linux 下 Glibc 入口函数 _start
伪代码
void _start()
{
%ebp = 0;
int argc = pop from stack
char** argv = top of stack; // esp
__libc_start_main(main, argc, argv, __lib_csu_init, __libc_csu_fini, edx, top of stack)
}
2 C/C++ 运行库
运行库: 入口函数 及其 所依赖的函数 + 标准库函数 的 函数集合
ANSI C 标准库: 24 个 C 头文件 组成 -> 轻量
(1) 变长参数
机制: 得益于 C 语言默认的 cdecl 调用惯例
的 自右向左压栈 传递
方式
实现思路: 4 个 宏
va_list // va_list ap;
1) 是 `指针`, 用于指向 `各变参`
2) 类型不明 => 最佳选择为 void* 或 char*
#define va_list char*
va_start(ap, lastNamedPara)
将 `va_list 指针 ap` 指向 `第1个变参`
#define va_start(ap, arg) ( ap = (va_list)&arg + sizeof(arg) )
va_arg(ap, type) // type currentUndefinedPara = va_arg(ap, type)
return `type 已知 的 当前变参值` + 移 ap 到 next 变参
#define va_arg(ap, type) ( *(type*)( (ap += sizeof(type) ) - sizeof(type) ) )
va_end(ap)
指针 ap 清 0
#define va_end(ap) (ap = (va_list)0 )
变参指针 ap
依次指向 各 变参
1) `必须用 va_start 初始化` 1 次, lastNamedPara 必须是 `最后1个 具名 arg`
2) 被 va_arg 移到 `type 已知` 的 `本变参` 的 `next 变参` 位置
int sum(unsigned num, ...)
{
int* p = &num + 1;
int ret = 0;
while(num--)
ret += *p++;
return ret;
}
int n = sum(3, 16, 38, 53);




网友评论