[读书笔记]程序员的自我修养(11)

本文介绍了运行库的功能,包括环境变量和参数数组、内存分配、程序启动流程、入口函数、I/O初始化、C语言标准库、变长参数宏、非局部跳转以及线程相关知识。重点讲解了mainCRTStartup流程、FILE结构、CRT的功能以及fread的实现。运行库在多线程中的角色和如何管理不同类型的变量和数据也在文中有所阐述。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第十一章 运行库

1. 环境变量和参数数组
---栈的增长方向--->
。。。0    env n    。。。    env 0    0    arg n    。。。 arg 0    argc

esp指向arg 0;old esp指向argc

2. 程序开始时分配内存用alloca,因为在程序的一开始堆还没有被初始化,而alloca是唯一可以不使用堆的动态分配机制。alloca可以再栈上分配任意大小的空间(只要栈的大小允许),并且在函数返回的时候会自动释放,就好像局部变量一样。函数退出时的退栈操作是直接将ESP的值赋为EBP的值。

3. mainCRTStartup总体流程
初始化和OS版本有关的全局变量
初始化堆
初始化I/O
获取命令行参数和环境变量
初始化C库的一些数据
调用main并记录返回值
检查错误并将main的返回值返回

main/wmain/WinMain/wWinMain等都不是程序的实际入口

4. FILE在Linux下叫文件描述符,windows下叫句柄,总是和内核的文件对象相关联
0,1,2代表标准输入stdin、标准输出stdout、标准错误输出stderr

MSVC的I/O初始化工作:
建立打开文件表
如果能够继承自父进程,那么从父进程获取继承的句柄
初始化标准输入输出

5. CRT的大致功能:
启动和退出:包括入口函数及入口函数所依赖的其他函数等
标准函数:有C语言标准规定的C语言标准库所拥有的函数实现
I/O:I/O功能的封装和实现
堆:堆的封装和实现
语言实现:语言中一些特殊功能实现
调试:实现调试功能的代码

6. C语言标准库
stdio.h :标准的输入输出,文件操作
ctype.h :字符操作
string.h :字符串操作
math.h :数学函数
stdlib.h :资源管理、格式转换
time.h :时间/日期
assert.h :断言
limits.h & float.h :各种类型上常数
stdarg.h :变长参数
setjmp : 非局部跳转

变长参数宏:
linux: #define printf(args...) fprintf(stdout, ##args)
windows: #define printf(...) fprintf(stdout, __VA_ARGS__)

例如:printf("%d%s",123, "hello") 被扩展成fprintf(stdout, "%d%s", 123, "hello")  

非局部跳转:
#include <setjmp.h>
#include <stdio.h>

jmp_buf b;
void f()
{
longjmp(b, 1);
}

int main()
{
if (setjmp(b))
{
    printf("World!");
}else
{
    printf("Hello ");
    f();
}
return 0;
}

打印:Hello World!

7. 运行库与多线程
线程私有:局部变量,函数的参数,TLS(线程局部存储)数据
线程之间共享(进程所有):全局变量,堆上数据,函数的静态变量,程序代码,打开文件

8.fread实现
size_t fread(void *buffer, size_t elementSize, size_t count, FILE *stream);
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);

size_t fread(void *buffer, size_t elementSize, size_t count, FILE *stream)
{
DWORD bytesRead=0;
BOOL ret=ReadFile(stream->_file, buffer, elementSize*count, &bytesRead, NULL);
if (ret)
   return bytesRead;
else
   return -1;
}

int fflush(FILE *stream)  flush指定文件的缓冲,若参数为NULL,则flush所有文件的缓冲

int setvbuf(FILE *stream, char *buf, int mode, size_t size)
无缓冲模式:_IONBF 该文件不使用任何缓冲
行缓冲模式:_IOLBF 仅对文本模式打开的文件有效,所谓行,即是指每收到一个换行符(\n或\r\n),就将缓冲flush掉
全缓冲模式:_IOFBF 仅当缓冲满时才进行flush

void setbuf(FILE *stream, char *buf)  等价于 (void)setvbuf(stream, buf, _IOFBF, BUFSIZE)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值