C语言预处理及特殊函数介绍(extern/exit/atexit/volatile/static/calloc/realloc等)PART TWO

来源:互联网 发布:指南针软件 不断打电话 编辑:程序博客网 时间:2024/06/05 16:45

8).使用exit和atexit终止程序

通用工具库<stdlib.h>提供了除从main函数正常返回之外的其他一些终止程序运行的方法如函数exit和atexit。

exit函数强制终止程序的运行就好像正常运行结束一样。当检测到一个输入错误或者欲处理的文件无法打开时,常常使用exit函数来结束程序运行。

atexit函数注册一个函数,这个函数必须在程序成功结束时调用——要么是程序执行到了main函数的末尾,要么是调用了exit函数使得程序结束。atexit函数接收指向欲注册函数的指针(即函数名)作为实参。这个在程序结束时被调用的函数不能没有实参,也不能返回一个值。

exit函数接收一个实参。这个实参通常是符号常量EXIT_SUCCESS或EXIT_FAILURE。如果使用EXIT_SUCCESS来调用exit函数,一个系统定义的、代表程序成功结束的数值将被返回给主调环境。如果使用EXIT_FAILURE来调用exit函数,将返回一个系统定义的、代表程序未成功结束的值。调用exit函数后,由atexit函数注册的所有函数,将按照与它们注册顺序相反的顺序被依次调用。所有与程序相联系的输入/输出流将被处理完,然后关闭,控制也将返回到主调环境中。

例:

#include <stdio.h>#include <stdlib.h>void print(void)int main(void){int answer;atexit(print);printf("Enter 1 to terminate program with function exit""\nEnter 2 to terminate program normally\n");scanf("%d",&answer);if(answer == 1){printf("Terminating program with function exit");exit(EXIT_SUCCESS);}printf("\nTerminating program by reaching the end of main\n");return 0;}void print(void){printf("Executing function print at program""termination\nProgram terminated\n");}

9).volatile类型限定符

当使用volatile来限定一个类型时,对这种类型对象的访问的内涵是依赖于系统实现的,这就意味着这个变量可能会被其他程序或者计算机硬件修改。


10).信号的处理

一个外部的异步事件或者信号能够引起程序提前结束。常见的事件有中断(Linux或Windows中键入Ctrl+C组合键)、非法指令、段越界、来自操作系统的终止命令和浮点数运算一场等。

信号处理函数库<signal.h>提供了基于函数signal的捕获(trap)异常事件的能力。函数signal接收两个实参——整型的信号编号和指向相应的信号处理函数的指针。信号可以通过函数raise来产生,该函数接收一个整型的信号编号作为实参。下图对<signal.h>中标准信号作了总结。


#include <stdio.h>#include <signal.h>#include <stdlib.h>#include <time.h>void signalHandler(int signalValue);int main(void){int i;int x;signal(SIGINT,signalHandler);srand (time(NULL));for(i = 1; i <= 100; i++){x = 1 + rand()%50;/*产生一个随机数*/if(x == 25){raise(SIGINT);}printf("%4d", i);/*每10个数输出一行*/if(i % 10 ==0){printf("\n");}}return 0;}void signalHandler(int signalValue){int response;printf("%s%d%s\n%s","Interrupt signal (",signalValue,") received.","Do you wish to continue (1 = yes or 2 = no)?");scanf("%d",&response);while(response != 1 && response != 2){printf("(1 = yes or 2 = no)?");scanf("%d",&response);}if(response == 1){signal(SIGINT,signalHandler);}else{exit(EXIT_SUCCESS);}}


10).动态内存分配:函数calloc和realloc

在快速的排序、查找和数据访问方面,数组要优于链表。但是数组属于静态数据结构。通用工具看<stdlib.h>提供了另外两个可以用于动态内存分配的函数calloc和realloc。这两个函数可用于创建并修改动态数组。

为了访问一个数组,可以将指向数组的指针当作下标来使用。这样,指向由函数calloc申请的一段连续的内存空间的指针就可以被当作一个数组下标来操作。


函数calloc的原型是:

void *calloc (size_t nmemb, size_t size);

其中两个实参nmemb和size分别表示数组元素的个数和每个元素的大小。函数calloc还同时将数组的每一个元素都初始化为0.如果申请成功,函数calloc返回一个指向申请到的内存空间的指针,否则返回一个NULL指针。

函数calloc和malloc最根本的差别是:calloc清空它申请到的内存空间,而malloc不这样。


函数realloc用于用来改变先前调用函数malloc、calloc或realloc申请到的一个对象的大小。如果新申请到的内存容量大于原先申请到的内存容量,则原先对象的内容不会被修改。否则只有不超过新对象大小的内容不会被修改。

函数realloc函数原型是:

void *realloc(void *ptr, size_t size);


其中两个实参ptr和size分别是指向原先对象的指针和这个对象的新长度。

如果ptr为NULL,则函数realloc的功能与malloc相同。

如果size为0,而ptr不为NULL,则ptr指向的对象所占的内存空间将被释放。

如果ptr不为NULL,而size大于0,则函数realloc将试图为这个对象申请一块新的内存空间。

如果申请失败,则ptr指向的对象不会被修改。

函数realloc要么返回一个指向新申请到的内存空间的指针,要么返回一个NULL指针表示申请失败。

0 0
原创粉丝点击