徐闻住房与城乡建设局网站wordpress文章页打赏
2026/4/18 14:27:15 网站建设 项目流程
徐闻住房与城乡建设局网站,wordpress文章页打赏,缪斯形象设计高级定制,院校门户网站建设方案一、main函数 C程序总是从main函数开始执行#xff0c;main函数的原型是#xff1a; int main(int argc,char *argv[]); 正如前面提到的#xff0c;argc是命令行参数的数目#xff0c;argv是指向个参数的指针组成的数组。 当内核执行C程序时#xff0c;在调用main前先调用…一、main函数C程序总是从main函数开始执行main函数的原型是int main(int argc,char *argv[]);正如前面提到的argc是命令行参数的数目argv是指向个参数的指针组成的数组。当内核执行C程序时在调用main前先调用一个特殊的启动例程。可执行文件将此例程指定为程序的起始地址--这是由编译器设置的而连接编译器则由c编译器调用通常是cc。启动例程从内核取得命令行参数和环境变量值然后按上述方式为调用main做好安排二、进程终止八种使进程终止的方式1从main返回正常终止2调用exit正常终止3调用_exit或_Exit正常终止4最后一个线程从启动例程返回正常终止5最后一个线程调用pthread_exit正常终止6调用abort异常终止7接收到信号并终止异常终止8最后一个线程取消对请求做出的响应异常终止1.exit函数区别_exit和_Exit函数立即进入内核而exit则先执行一些清理处理调用执行终止处理程序关闭所有标准IO流等等然后进入内核#include stdlib.h void exit(int status); void _Exit(int status); #include unistd.h void _exit(int status);exit函数总是会调用fclose函数关闭已经打开的标准IO流。status参数称为终止状态如果调用时未指定终止状态或mian执行了一个无返回值的return或main没有声明返回的类型为整形则该进程的终止状态使未定义的。可以使用命令echo $?来打印命令的退出状态码return 0;等价于exit(0);2.atexit函数按照ISO C规定一个进程可以登记多达32个终止处理函数调用atexit函数来登记终止处理函数。#include stdlib.h int atexit(void (*func)(void));- atexit函数的参数是一个函数地址调用时不需要传递任何参数不期待返回任何值。- exit调用这些终止处理函数的顺序与登记顺序相反重复登记一个函数会导致重复调用。根据ISO C标准exit首先调用各终止处理函数然后按需调用fclose。POSIX.1扩展了ISO C标准若程序调用了exec家族的一个函数其作用是在当前程序在exec调用处启动一个新的程序旧的进程立即终止不再运行则清除旧程序的所有终止处理函数然后执行新程序内核使程序执行的唯一方法是调用一个exec函数。进程资源终止的唯一方法是显式或隐式的调用_exit或_Exit。进程也可以非结缘的由一个信号使其终止。例#include apue.h static void my_exit1(void); static void my_exit2(void); int main(void){ if(atexit(my_exit2)!0) err_sys(cant register my_exit2); if(atexit(my_exit1)!0) err_sys(cant register my_exit1); if(atexit(my_exit1)!0) err_sys(cant register my_exit1); printf(main is done\n); return(0); } static void my_exit1(void){ printf(first exit handler); } static void my_exit2(void){ printf(Second exit handler); }最终打印main is donefirst exit handlerfirst exit handlersecond exit handleigemei三、环境表每个程序都有一个环境表是一个字符指针数组其中每个指针包含一个以null结束的c字符串的地址。全局变量environ包含了该指针数组的地址extern char **environ;其中每个字符串结尾都显式的有一个null字符。我们称environ为环境指针指针数组为环境表。通常使用getenv和putenv函数来访问特定的环境变量后面会讲到四、C程序的存储空间布局1.代码段正文段储存程序指令通常正文段是可共享的所以即使多次调用的程序也只需要保存一个副本即可。正文段只读防止程序意外修改自身指令。2.初始化数据段只读数据段已初始化的数据段只读数据段中存储字符串常量、const变量等已初始化的数据段初始值来自可执行文件例如c程序中出现在任何函数之外并且已赋初始值的声明。3.非初始化数据段BSS段在程序开始之前将此段内的数据初始化为0或空指针例如c程序中出现在任何函数之外并且未赋初始值的声明。4.栈自动变量局部变量以及每次函数调用时所需保存的信息返回地址即函数结束后返回到哪、调用者环境即保存的寄存器值、传递给函数的参数、局部变量都存放在此段中。每次调用函数时返回的地址以及调用者的环境信息都存放在栈中。通过这种方式调用栈可以递归调用c函数递归函数每次调用自身时就使用一个新的栈帧因此一个函数调用实例中的变量及不会影响另一个函数调用实例中的变量一个栈帧对应一次调用每个栈帧相互独立。栈是编译器自动管理的。地址由高向低增长。5.堆进行动态内存分配由程序员手动管理地址由低向高增长容易出现内存碎片、内存泄漏等问题。典型的地址空间- 栈底和堆顶之间有很大的虚地址空间- 有图中注意到未初始化的数据段内容并不存放在磁盘上的程序文件中因为内核在程序开始运行之前将它们都设置为0.需要存放在程序文件中的段只要正文段和初始化数据段。- size命令查看程序的空间占用情况五、存储器分配ISO C说明了三个用于存储空间动态分配的函数。1malloc分配指定字节数的存储区此存储区中的初始值不确定。2calloc为指定数量具有指定长度的对象分配存储空间该空间中每一位都初始化为03realloc更改以前分配的长度可增加或减少。增加长度时可能会将目标移动到另一个足够大的区域新增区的初始值不确定。#include stdlib.h void *malloc(size_t size); void *calloc(size_t nobj,size_t size); void *realloc(void *ptr,size_t newsize);//newsize是指新的存储区的长度 //成功则返回非空指针失败则返回NULL void free(void *ptr);因为这三个函数都返回通用指针void*所以如果在程序中包括了stdlib.h库获得函数原型则我们将返回指针赋予一个不同类型的指针时就不需要显式的执行类型强制转换。什么是内存对齐内存对齐是指数据在内存中的起始地址必须是某个值的整数倍这个值由数据类型决定这是硬件的要求不是语言的规定。例如char c; // 1字节对齐任何地址都可以 short s; // 2字节对齐地址必须是2的倍数 int i; // 4字节对齐地址必须是4的倍数 double d; // 8字节对齐地址必须是8的倍数 long long l;// 8字节对齐malloc返回的指针一定是适当对齐的可以用于任何数据对象。这句话是什么意思假设本系统最严格的要求是dobule类型参考上述例子为8字节对齐那么这三个函数返回的指针就会自动对齐到8字节这样对于char的1字节、short的2字节、int的4字节都可以对齐了所以我们可以将返回指针赋予任何一个类型的指针。free释放ptr指向的存储空间。被释放的空间通常被送入可用存储区池以后可以再次进行动态分配。realloc可以增加或减少原分配区的长度例如如果为一个数组分配存储空间512然后再运行过程中填充他但一段时间后发现原先的长度不够就可以调用realloc扩充相应空间。需要注意的是不能使用realloc延长一个静态的数组我们常用的int arr[10]{0}就是静态分配大多数实现所分配的空间比所要求的大一点这是因为要有额外的空间来记录管理信息分配块的长度、指向下一个分配块的指针等等。这会导致一个严重的问题假如有一个分配块已经写满而程序继续向其中写入数据那么数据就会写入下一个分配块的管理信息。其他致命错误释放一个已经释放了的块调用free时所用的指针不是三个alloc函数的返回值等等。开辟的空间忘记释放这种情况被称为泄露。alloca函数它的调用序列与malloc相同但是它再当前函数的栈帧上分配空间。优点是当函数返回时自动释放它所使用的栈帧不用手动释放。缺点是alloca函数增加了栈帧的长度而某些系统在函数已经被调用后就不能再增加栈帧所以这些系统并不支持alloca函数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询