C语言参考手册

合集下载

C语言标准参考手册

C语言标准参考手册
Traditional C 现在只会在一些非常老的代码中才能见到了,除非你在维护旧代 码,否则不应该再使用它。
所以,个人觉得当前还是以 C89(包括 C95)标准为主。
1 引言
本手册描述的 c 语言是 1988 年 10 月 31 日提交给 ANSI 的草案,批准号为“美国 国家信息系统标准―C 程序设计语言,X3.159-1989”。尽管我们已非常小心, 以便这个手册的介绍可以信赖,但它毕竞不是标准本身,而是对标准的一个解释。 这个手册的安排基本与标准相似,也与本书的第 1 版相似,但是对细节的组织是 不同的。本手册给出的语法与标难是一样的,只是有少量产生式有所修改,词法 元素和预处理器的定义也非形式化。注释部分说明了 ANSI 标准 C 与本书第 1 版 介绍的或其他编译器所支持的语言的细微差别。
1.3 C95
这是对 C89 的一个修订和扩充,称为“C89 with Amendment 1”或 C95,严格说 来并不是一个真正的标准。
C95 的主要改动:
• 3 个新标准头文件:iso646.h、wctype.h、wchar.h; • 一些新的标记(token)和宏(macro); • 一些新的 printf/scanf 系列函数的格式符; • 增加了大量的宽字符和多字节字符函数、常数和类型。
• 浮点常量的后缀是新增加的。
2.5.4 枚举常量
定义为枚举符的标识符是 int 类型的常量(见 8.4 节)。
2.6 字符串字面值
字符串字面值也叫字符毒常量,是由双引号括起来的一个字符序列,如"..."。 字符串的类型为“字符数组”,存储类为 static(见 4 节),由给定的字符来初 始化。相同的字符串字面值是否看做是不同的取决于具体的实现。如果程序试图 改变字符串字面值,那么该行为是未定义的。

c程序设计语言(第2版)

c程序设计语言(第2版)

c程序设计语言(第2版)C程序设计语言(第2版)是一本经典的计算机编程教材,由著名的计算机科学家Brian W. Kernighan和Dennis M. Ritchie共同撰写。

这本书首次出版于1978年,第2版于1988年出版。

它通常被简称为K&R,是C语言编程的权威指南,对初学者和有经验的程序员都具有极高的参考价值。

书籍概述这本书全面介绍了C语言的语法、语义和编程技巧。

它不仅涵盖了C语言的基本元素,如变量、运算符、控制结构、函数和数组,还深入探讨了更高级的主题,包括指针、结构、联合、枚举、位操作和预处理器。

第一部分:基础第一部分主要介绍了C语言的基础知识。

它解释了C语言的基本数据类型和运算符,以及如何使用它们来执行基本的算术和逻辑运算。

此外,它还介绍了控制流语句,如if语句、switch语句、while循环和for循环,这些是任何编程语言中实现条件和循环逻辑的基础。

第二部分:函数第二部分专注于函数的定义和使用。

函数是C语言中实现代码重用和模块化的关键。

这部分详细讨论了函数的定义、声明、调用以及如何传递参数。

它还介绍了递归函数的概念,这是一种特殊的函数,它在执行过程中调用自身。

第三部分:指针第三部分深入探讨了指针的概念。

指针是C语言中非常强大的特性,允许程序员直接操作内存地址。

这部分解释了指针的基本概念,包括如何声明指针、指针的算术运算以及指针与数组的关系。

此外,它还介绍了指针在函数参数传递中的应用,以及如何使用指针实现动态内存分配。

第四部分:结构、联合和枚举第四部分介绍了C语言中的复合数据类型,包括结构、联合和枚举。

结构允许将不同类型的数据组合成一个单一的数据类型,联合允许在同一内存位置存储不同的数据类型,而枚举提供了一种定义命名常量的方法。

这部分还讨论了如何使用这些复合类型来创建复杂的数据结构。

第五部分:预处理器和宏第五部分介绍了C语言的预处理器和宏。

预处理器提供了一种在编译之前处理源代码的方法,包括文件包含、条件编译和宏定义。

合泰C语言用户手册

合泰C语言用户手册

函数 ....................................................................................................27
数组 ....................................................................................................28
注释 ......................................................................................................2
标识符..........................................................................................................3
位数据类型 ........................................................................................25
内嵌式汇编语言 ................................................................................26
条件运算符 ..........................................................................................9
逗号运算符 ..........................................................................................9

c语言参考手册

c语言参考手册

c语言参考手册1. 前言C语言是一种广泛应用于软件开发领域的编程语言,具有简洁、高效、灵活等特点。

本参考手册旨在为C语言学习者提供详细、全面的语法和库函数参考信息,帮助他们快速掌握和应用C语言。

2. 数据类型2.1 基本数据类型C语言支持基本的数据类型,包括整数、浮点数、字符等。

在本节中,将详细介绍这些数据类型的定义、使用和限制。

2.2 数组和指针数组和指针是C语言中重要的数据结构,本节将介绍它们的定义、访问和操作方法,以及二者之间的关系和区别。

2.3 结构体和联合体结构体和联合体是C语言中用于组织和管理复杂数据的重要工具。

在本节中,将介绍它们的定义、访问和操作方法,以及结构体与联合体之间的区别。

3. 控制流程3.1 条件语句条件语句(如if语句、switch语句)是C语言中用于根据不同条件执行不同代码块的重要结构。

本节将详细介绍条件语句的语法和使用方法。

3.2 循环语句循环语句(如for循环、while循环)允许程序重复执行某段代码,以实现特定的逻辑功能。

本节将介绍各种循环语句的用法和特点。

3.3 跳转语句跳转语句(如break语句、continue语句、goto语句)在C语言中用于控制程序的跳转流程。

本节将详细介绍这些跳转语句的使用规则和注意事项。

4. 函数和库函数4.1 函数定义与调用函数是C语言中实现模块化编程的重要手段。

本节将介绍函数的定义、声明和调用方法,以及参数传递和返回值的规则。

4.2 标准库函数标准库函数是C语言提供的一系列功能强大的预定义函数,方便程序员加快开发效率。

本节将列举一些常用的标准库函数,并说明其使用方法和注意事项。

5. 高级特性5.1 指针和动态内存分配指针是C语言中的重要概念,可以用于灵活地操作内存地址和数据。

本节将介绍指针的使用方法,以及动态内存分配的相关概念和函数。

5.2 文件操作文件操作是C语言中处理输入输出的重要方式,本节将介绍文件的打开、关闭、读写等操作方法,以及文件指针的概念和函数。

C手册

C手册
? 定义了 C标准库;
? 新的预处理命令和特性;
? 函数原型(prot ot ype);
? 新关键字:const 、vol at i l e、si gned;
? 宽字符、宽字符串和多字节字符;
? 转化规则、声明(decl arat i on)、类型检查的改变。
1. 3 C 95
D enni s M . R i t chi e. Prent i ce H al l PTR (Apri l 1, 1988), 0131103628. ”附
录 A的一份拷贝,在此作为 C 89 标准以供需要时查阅。
同时也提供中文版本,内容来自该书对应的中译版“《C程序设计语言》,徐宝
2. 5 常量
常量
共有几种类型的常量, 它们每一种都有一个数据类型, 基本类型将在 4. 2 节讨论。
常量:
整数常量
字符常量
浮点常量
枚举常量
2. 5. 1 整数常量
整数常量
整数常量由一串数字序列组成。如果它以 0(数字 0)开始,那么是八进制数.否
描述可算作“正式”的标准,所以此时的 C也称为“K&R ”C 。
期间 C语言一直不断的发生细微的变化,各编译器厂商也有自己的扩展, 这个过
程一直持续到 20世纪 80 年代末。
1. 2 C 89
考虑到标准化的重要,AN SI (Am eri can N at i onal St andards I nst i t ut e)制定了
? 一些新的 pri nt f / scanf 系列函数的格式符;
? 增加了大量的宽字符和多字节字符函数、常数和类型。
1. 4 C 99

C语言库函数手册

C语言库函数手册

C语言库函数手册转载说明:可能有些函数已经过时,但从学习的角度来看,还是有一定的参考价值。

分类函数,所在函数库为ctype.hint isalpha(int ch) 若ch是字母('A'-'Z','a'-'z')返回非0值,否则返回0int isalnum(int ch) 若ch是字母('A'-'Z','a'-'z')或数字('0'-'9')返回非0值,否则返回0int isascii(int ch) 若ch是字符(ASCII码中的0-127)返回非0值,否则返回0int iscntrl(int ch) 若ch是作废字符(0x7F)或普通控制字符(0x00-0x1F)返回非0值,否则返回0int isdigit(int ch) 若ch是数字('0'-'9')返回非0值,否则返回0int isgraph(int ch) 若ch是可打印字符(不含空格)(0x21-0x7E)返回非0值,否则返回0 int islower(int ch) 若ch是小写字母('a'-'z')返回非0值,否则返回0int isprint(int ch) 若ch是可打印字符(含空格)(0x20-0x7E)返回非0值,否则返回0 int ispunct(int ch) 若ch是标点字符(0x00-0x1F)返回非0值,否则返回0int isspace(int ch) 若ch是空格(' '),水平制表符('\t'),回车符('\r'),走纸换行('\f'),垂直制表符('\v'),换行符('\n')返回非0值,否则返回0int isupper(int ch) 若ch是大写字母('A'-'Z')返回非0值,否则返回0int isxdigit(int ch) 若ch是16进制数('0'-'9','A'-'F','a'-'f')返回非0值,否则返回0int tolower(int ch) 若ch是大写字母('A'-'Z')返回相应的小写字母('a'-'z')int toupper(int ch) 若ch是小写字母('a'-'z')返回相应的大写字母('A'-'Z')数学函数,所在函数库为math.h、stdlib.h、string.h、float.hint abs(int i) 返回整型参数i的绝对值double cabs(struct complex znum) 返回复数znum的绝对值double fabs(double x) 返回双精度参数x的绝对值long labs(long n) 返回长整型参数n的绝对值double exp(double x) 返回指数函数ex的值double frexp(double value,int *eptr) 返回value=x*2n中x的值,n存贮在eptr中double ldexp(double value,int exp); 返回value*2exp的值double log(double x) 返回logex的值double log10(double x) 返回log10x的值double pow(double x,double y) 返回xy的值double pow10(int p) 返回10p的值double sqrt(double x) 返回+√x的值double acos(double x) 返回x的反余弦cos-1(x)值,x为弧度double asin(double x) 返回x的反正弦sin-1(x)值,x为弧度double atan(double x) 返回x的反正切tan-1(x)值,x为弧度double atan2(double y,double x) 返回y/x的反正切tan-1(x)值,y的x为弧度double cos(double x) 返回x的余弦cos(x)值,x为弧度double sin(double x) 返回x的正弦sin(x)值,x为弧度double tan(double x) 返回x的正切tan(x)值,x为弧度double cosh(double x) 返回x的双曲余弦cosh(x)值,x为弧度double sinh(double x) 返回x的双曲正弦sinh(x)值,x为弧度double tanh(double x) 返回x的双曲正切tanh(x)值,x为弧度double hypot(double x,double y) 返回直角三角形斜边的长度(z),x和y为直角边的长度,z2=x2+y2double ceil(double x) 返回不小于x的最小整数double floor(double x) 返回不大于x的最大整数void srand(unsigned seed) 初始化随机数发生器int rand() 产生一个随机数并返回这个数double poly(double x,int n,double c[])从参数产生一个多项式double modf(double value,double *iptr)将双精度数value分解成尾数和阶double fmod(double x,double y) 返回x/y的余数double frexp(double value,int *eptr) 将双精度数value分成尾数和阶double atof(char *nptr) 将字符串nptr转换成浮点数并返回这个浮点数double atoi(char *nptr) 将字符串nptr转换成整数并返回这个整数double atol(char *nptr) 将字符串nptr转换成长整数并返回这个整数char *ecvt(double value,int ndigit,int *decpt,int *sign)将浮点数value转换成字符串并返回该字符串char *fcvt(double value,int ndigit,int *decpt,int *sign)将浮点数value转换成字符串并返回该字符串char *gcvt(double value,int ndigit,char *buf)将数value转换成字符串并存于buf中,并返回buf的指针char *ultoa(unsigned long value,char *string,int radix)将无符号整型数value转换成字符串并返回该字符串,radix为转换时所用基数char *ltoa(long value,char *string,int radix)将长整型数value转换成字符串并返回该字符串,radix为转换时所用基数char *itoa(int value,char *string,int radix)将整数value转换成字符串存入string,radix为转换时所用基数double atof(char *nptr) 将字符串nptr转换成双精度数,并返回这个数,错误返回0int atoi(char *nptr) 将字符串nptr转换成整型数, 并返回这个数,错误返回0long atol(char *nptr) 将字符串nptr转换成长整型数,并返回这个数,错误返回0 double strtod(char *str,char **endptr)将字符串str转换成双精度数,并返回这个数, long strtol(char *str,char **endptr,int base)将字符串str转换成长整型数,并返回这个数,int matherr(struct exception *e)用户修改数学错误返回信息函数(没有必要使用)double _matherr(_mexcep why,char *fun,double *arg1p,double *arg2p,double retval)用户修改数学错误返回信息函数(没有必要使用)unsigned int _clear87() 清除浮点状态字并返回原来的浮点状态void _fpreset() 重新初使化浮点数学程序包unsigned int _status87() 返回浮点状态字目录函数,所在函数库为dir.h、dos.hint chdir(char *path) 使指定的目录path(如:"C:\\WPS")变成当前的工作目录,成功返回0int findfirst(char *pathname,struct ffblk *ffblk,int attrib)查找指定的文件,成功返回0pathname为指定的目录名和文件名,如"C:\\WPS\\TXT"ffblk为指定的保存文件信息的一个结构,定义如下:┏━━━━━━━━━━━━━━━━━━┓┃struct ffblk ┃┃{ ┃┃ char ff_reserved[21]; /*DOS保留字*/┃┃ char ff_attrib; /*文件属性*/ ┃┃ int ff_ftime; /*文件时间*/ ┃┃ int ff_fdate; /*文件日期*/ ┃┃ long ff_fsize; /*文件长度*/ ┃┃ char ff_name[13]; /*文件名*/ ┃┃} ┃┗━━━━━━━━━━━━━━━━━━┛attrib为文件属性,由以下字符代表┏━━━━━━━━━┳━━━━━━━━┓┃FA_RDONLY 只读文件┃FA_LABEL 卷标号┃┃FA_HIDDEN 隐藏文件┃FA_DIREC 目录┃┃FA_SYSTEM 系统文件┃FA_ARCH 档案┃┗━━━━━━━━━┻━━━━━━━━┛例:struct ffblk ff;findfirst("*.wps",&ff,FA_RDONLY);int findnext(struct ffblk *ffblk) 取匹配finddirst的文件,成功返回0void fumerge(char *path,char *drive,char *dir,char *name,char *ext) 此函数通过盘符drive(C:、A:等),路径dir(\TC、\BC\LIB等),文件名name(TC、WPS等),扩展名ext(.EXE、.COM等)组成一个文件名存与path中.int fnsplit(char *path,char *drive,char *dir,char *name,char *ext) 此函数将文件名path分解成盘符drive(C:、A:等),路径dir(\TC、\BC\LIB等),文件名name(TC、WPS等),扩展名ext(.EXE、.COM等),并分别存入相应的变量中.int getcurdir(int drive,char *direc) 此函数返回指定驱动器的当前工作目录名称drive 指定的驱动器(0=当前,1=A,2=B,3=C等)direc 保存指定驱动器当前工作路径的变量成功返回0char *getcwd(char *buf,iint n) 此函数取当前工作目录并存入buf中,直到n个字节长为为止.错误返回NULLint getdisk() 取当前正在使用的驱动器,返回一个整数(0=A,1=B,2=C等)int setdisk(int drive) 设置要使用的驱动器drive(0=A,1=B,2=C等), 返回可使用驱动器总数int mkdir(char *pathname) 建立一个新的目录pathname,成功返回0int rmdir(char *pathname) 删除一个目录pathname,成功返回0char *mktemp(char *template) 构造一个当前目录上没有的文件名并存于template中char *searchpath(char *pathname) 利用MSDOS找出文件filename所在路径,,此函数使用DOS的PATH变量,未找到文件返回NULL进程函数,所在函数库为stdlib.h、process.hvoid abort() 此函数通过调用具有出口代码3的_exit写一个终止信息于stderr,并异常终止程序。

C语言参考手册之函数库

C语言参考手册之函数库

版权说明:本资料内容摘录自《C程序设计语言(第二版)》K&R著 徐宝文 李志译 尤晋元审校机械工业出版社出版 一书。

版权属原作者和出版社所有。

制作本资料为了我本人学习和参考,非商业用途。

建议读者阅读原书学习比较好,它更详细。

目录:附录B:标准库介绍标准库的组成,及使用注意。

B.1 输入与输出:<stdio.h>主要介绍流的概念等。

B.1.1 文件操作主要介绍 fopen(), freopen(), fflush(), fclose(), remove(), rename(), tmpfile(), tmpnam(), setvbuf(),setbuf()等。

B.1.2 格式化输出主要介绍 printf(), fprintf(), sprintf(), vprintf(), vfprintf(), vsprintf()等。

B.1.3 格式化输入主要介绍 fscanf(), scanf(), sscanf()等。

B.1.4 字符输入/输出函数主要介绍 fgetc(), fgets(), fputc(), fputs(), getc(), gets(), putc(),puts(), putchar(), ungetc()等。

B.1.5 直接输入输出主要介绍 fread()和fwrite()。

B.1.6 文件定位函数主要介绍 fseek(), ftell(), rewind(), fgetpos(), fsetpos()等。

B.1.7 错误处理函数主要介绍 clearerr(), feof(), ferror(), perror()等。

B.2 字符类别测试:<ctype.h>主要介绍 isalnum(c), isalpha(c), iscntrl(c), isdigit(c), … , tolower(c), toupper(c)等。

B.3 字符串函数:<string.h>主要介绍 strcpy(),strncpy(), strcat(), strncat(), strcmp(), strncmp(), strchar(), strrchr(), strspn(), strcspn(), strpbrk(), strstr(), strlen(), strerror(), strtok()等。

C语言标准参考手册

C语言标准参考手册

C语言标准参考手册C语言是一种广泛应用于系统软件开发和嵌入式系统领域的高级编程语言。

为了确保C语言的标准化和统一性,C语言标准参考手册被广泛采纳和使用。

在本篇文章中,将向您介绍C语言标准参考手册的结构和内容,并探讨其在C语言开发中的重要性。

一、引言C语言标准参考手册是由国际标准化组织(ISO)和美国国家标准学会(ANSI)联合发布的C语言的标准文档。

其目的是为了促进不同平台上的代码可移植性,并确保C语言在不同系统中的一致性。

二、手册结构C语言标准参考手册主要由以下几个部分组成:1. 标准库说明:该部分介绍了C语言标准库中提供的函数、宏等各种功能,并详细描述了各种库函数的使用方法和参数。

2. 语言特性说明:该部分介绍了C语言的语法、语义、数据类型、控制流以及各种运算符等基本语言特性。

3. 标准宏定义:该部分列举了C语言标准中定义的各种宏,并解释了它们的作用和用法。

4. 标准兼容性:该部分描述了C语言标准在不同编译器中的兼容性问题,以及应遵循的最佳实践和常见的编译错误。

5. 编译指令和预处理器:该部分介绍了C语言中的编译指令、预处理器以及它们的功能和使用方法。

三、内容详解1. 标准库说明:C语言标准库包括标准输入输出库(stdio.h)、数学库(math.h)、字符串处理库(string.h)等。

标准库中的函数提供了丰富的功能,比如输入输出操作、数学计算、字符串处理、内存管理等。

2. 语言特性说明:C语言具有丰富的语言特性,包括基本的数据类型(整型、浮点型、字符型等)、运算符、变量和常量的定义、控制流程(条件语句、循环语句)以及函数定义等。

标准参考手册详细描述了这些特性的语法和语义。

3. 标准宏定义:C语言标准定义了一些宏,这些宏可以用于条件编译和编译器相关的操作。

例如,宏__FILE__和__LINE__可以用于在源代码中插入当前文件名和行号,便于调试和错误定位。

4. 标准兼容性:C语言的标准参考手册对于编译器的实现提供了指导性的要求。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

版权说明:本资料内容摘录自《C程序设计语言(第二版)》K&R著 徐宝文 李志译 尤晋元审校 机械工业出版社出版 一书。

版权属原作者和出版社所有。

制作本资料为了我本人学习和参考,非商业用途。

建议读者阅读原书学习比较好,它更详细。

目录:A.12 预处理主要介绍预处理器的功能和预处理的过程。

A.12.1三字符序列主要介绍 ??=, ??(, ??<等三字符序列。

A.12.2 行连接主要介绍反斜杠\结束的指令行处理过程。

A.12.3 宏定义和扩展主要介绍#define 标识符 记号序列,#define 标识符(标识符表opt) 记号序列,#undef 标识符,还有#和##等一些东西,有一些例子。

A.12.4 文件包含主要介绍#include <文件名>和#include “文件名”指令。

A.12.5 条件编译介绍#if 常量表达式/#ifdef 标识符/#ifndef 标识符,#elif 常量表达式,#else,#endif语句。

A.12.6 行控制介绍#line指令。

A.12.7 错误信息生成介绍#error指令。

A.12.8 pragma介绍#pragma。

A.12.9 空指令介绍空指令#。

A.12.10 预定义名字介绍__LINE__, __FILE__, __DATE__, __TIME__, __STDC__等。

A.12 预处理 返回目录预处理器执行宏替换,条件编译以及包含指定的文件。

以#开头的命令行(“#”前可以有空格)就是预处理器处理的对象。

这些命令行的语法独立于语言的其它部分,他们可以出现在任何地方,其作用可以延续到所在编译单元的末尾(与作用域无关)。

行边界是有实际意义的;每一行都将单独进行分析(有关如何将行连接起来的详细信息参考A.12.2节)。

对预处理器而言,记号可以是任何语言记号,也可以是类似于#include指令(参见A.12.4节)中表示文件名的字符序列。

此外,所有未进行其它定义的字符都将被认为是记号。

但是,在预处理器指令行中,除空格,横向制表符外的其它空白字符的作用是没有定义的。

预处理过程在逻辑上可以划分为几个连续的阶段(在某些特殊的实现中可以缩减)。

1) 首先,将A.12.1节所述的三字符序列替换为等价字符。

如果操作系统环境需要,还要在原文件的各行之间插入换行符。

2) 将指令行中位于换行符前的反斜杠符\删掉,以把各指令行连接起来(参见A.12.2节)。

3) 程序分成用空白符分割的记号。

注释将被替换为一个空白符。

接着执行预处理指令,并且进行宏扩展(参见A.12.3节~A.12.10节)。

4) 将字符常量和字符串字面值中的转义字符序列替换为等价字符,然后把相邻的字符串字面值连接起来。

5) 收集必要的程序和数据,并将外部函数和对象的引用与其定义连接,翻译经过以上处理的结果,然后与其它程序和库连接起来。

A.12.1 三字符序列 返回目录C语言源程序的字符集是7位ASCII码的子集,但它是ISO 646-1983不变代码集的超集。

为了将程序通过这种缩减的字符集表示出来,下列所示的所有三字符序列都要用相应的单个字符替换,这种替换在进行所有其它处理之前进行。

??= # ??( [ ??< {??/ \ ??) ] ??> }??’ ^ ??! | ??- ~除此之外不进行其它替换。

说明:三字符序列是ANSI标准新引入的特征。

A.12.2 行连接通过将以反斜杠\结束的指令行末尾的反斜杠和其后的换行符删除掉,可以将若干指令行合并一行。

这种处理要在分隔记号之前进行。

A.12.3 宏定义和扩展 返回目录类似于下列形式的控制指令:#define 标识符 记号序列将使得预处理器把该标识符后续出现的各个实例用给定的记号序列替换。

记号序列前后的空白符将被丢弃掉。

第二次用#define指令定义同一个标识符是错误的,除非第二次定义的标记序列与第一次相同(所有的空白分隔符将被认为是相同的)。

类似于下列形式的指令行:#define 标识符(标识符表opt) 记号序列是一个带有形式参数(由标识符表指定)的宏定义,其中第一个标识符与圆括号(之间没有空格。

同第一种形式一样,记号序列前后的空白符都将被丢掉。

如果要对宏进行重新定义,则必须保证其形式参数个数、拼写及记号序列都必须与前面的定义相同。

类似于下列的控制指令:#undef 标识符用于取消标识符的预处理器定义。

将#undef应用于未知标识符(即未用#define指令定义的标识符)并不会导致错误。

按照第二种形式定义宏时,宏标识符(后面可以跟一个空白字符,空白符是可选的)及其后用一对圆括号括起来的、由逗号分隔的记号序列就构成了一个宏调用。

宏调用的实际参数使用逗号分隔的记号序列,用引号或嵌套的括号括起来的逗号不能用于分隔实际参数。

在处理过程中,实际参数不能进行宏扩展。

宏调用时,实际参数的数目必须与定义中的形式参数的数目匹配。

实际参数被分离后,前导和尾部的空白符被删除。

随后,由各实际参数产生的记号序列将替换未用引号引起来的相应形式参数的标识符(位于宏的替换记号序列中)。

除非替换序列中形式参数的前面有一个#符号,或者其前面或后面有一个##符号,否这,在插入前要对宏的实际参数记号进行检查,并在必要时进行扩展。

两个特殊的运算符会影响替换过程。

首先,如果替换记号序列中的某个形式参数前面直接是一个#符号(它们之间没有空白符),相应形式参数的两边将被加上双引号(″),随后,#和形式参数标识符将被用引号引起来的实际参数替换。

实际参数中的字符串字面值、字符常量两边或内部的每个双引号(″)或反斜杠(\)前面都要插入一个反斜杠(\).其次,无论哪种宏的定义记号序列中包含一个##运算符,在形式参数替换后都要把##及前后的空白符都删除掉,以便将相邻记号连接起来形成一个新记号。

如果这样产生的记号无效,或者结果依赖于##与算符的处理顺序,则结果没有定义。

同时,##也可以不出现在替换记号序列的开头和结尾。

对这两种类型的宏,都要重复扫描替换记号序列以查找更多的已定义标识符。

但是,当某个标识符在某个扩展中被替换后,再次扫描并再次遇到此标识符是不再对其执行替换,而是保持不变。

即使执行宏扩展后得到的最终结果以#打头,也不认为它是预处理指令。

说明:有关宏扩展处理的细节信息,ANSI标准比第一版描述得更详细。

更重要的变化是加入了#和##与算符,这就使得引用和连接成为可能。

某些新规则(特别是与连接有关的规则)比较独特(参见下面的例子)。

例如,这种功能可以用来定义“表示常量”,如下例所示:#define TABSIZE 100int table[TABSIZE];定义#define ABSDIFF(a, b) ((a)>(b) ? (a)-(b) : (b)-(a))定义了一个宏,它返回两个参数之差的绝对值。

与执行相同功能的函数所不同的是,参数与返回值可以是任意算术类型,甚至可以是指针。

同时,参数可能有副作用,而且需要计算两次,一次进行测试,一次则生成值。

假定有下列定义:#define tempfile(dir) #dir ″/%s″宏调用tempfile(/usr/tmp)将生成″/usr/tmp″″/%s″随后,该结果将被连接为一个单个的字符串。

给定下列定义:#define cat(x, y) x ## y那么,宏调用cat(var, 123)将生成var 123。

但是,宏调用cat(cat(1,2),3)没有定义:##阻止了外层调用的参数的扩展。

因此,他将生成下列记号串:cat( 1 , 2 )3并且,)3不是一个合法的记号,他由第一个参数的最后一个记号与第二个参数的第一个记号连接而成。

如果在引入第二层的宏定义,如下所示:#define xcat(x,y) cat(x,y)我们就可以得到正确结果。

xcat(xcat(1,2),3)将生成123,因为xcat自身的扩张不包含##运算符。

类似地,ABSDIFF(ABSDIFF(a,b),c)将生成所期望的经完全扩展后的结果。

A.12.4 文件包含 返回目录下列形式的控制指令:#include <文件名>将把该行替换为文件名指定的文件的内容。

文件名不包含>或换行符。

如果文件名中包含字符″、‘、\或/*,则其行为没有定义。

预处理器将在某些特定的位置查找指定的文件,查找的位置与具体的实现相关。

类似地,下列形式的控制指令:#include “文件名”首先从源文件的位置开始搜索指定文件(搜索过程与具体的实现相关),如果没有找到指定的文件,则按照第一种定义的方式处理。

如果文件名中包含字符″、’、\或/*,其结果仍然是没有定义的,但是可以使用字符〉。

最后,下列形式的指令行:#include 记号序列同上述两种情况都不同,它将按照扩展普通文本的方式扩展记号序列进行解释。

记号序列必须被解释为<…>或″…″两种形式之一,然后再按照上述方式进行相应的处理。

#include 文件可以嵌套。

A.12.5 条件编译 返回目录对一个程序的某些部分可以进行条件编译。

条件编译的语法形式如下:预处理器条件:if行 文本 elif部分opt else部分opt #endifif行:#if 常量表达式#ifdef 标识符#ifndef 标识符elif部分:#elif 常量表达式else部分:else行 文本else行:#else其中,每个条件编译指令(if行,elif行,else行及#endif)在程序中均单独占一行。

预处理器一次对#if以及后续的#elif行中的常量表达式进行计算,直到发现某个指令的常量表达式为非0值为止,这时将放弃值为0的指令行后面的文本。

常量表达式不为0的#if和#elif指令后面的文本将按照其他普通程序代码一样进行编译。

在这里,“文本”是指任何不属于条件编译指令结构的程序代码,它可以包含预处理指令,可以为空。

一旦预处理器发现某个#if或#elif条件编译指令中的常量表达式的值不为0,并选择其后的文本供以后的编译阶段使用时,后续的#elif和#else条件编译指令及相应的文本将被放弃。

如果所有常量表达式的值都是0,并且该条件编译指令链中包含一条#else指令,则将选择#else指令之后文本。

除了对条件编译指令的嵌套进行检查之外,条件编译指令的无效分支(即条件值为假的分支)控制的文本都将忽略。

#if和#elif中的常量表达式将执行通常的宏替换。

并且,任何下列形式的表达式:define 标识符或define(标识符)都将在执行宏扫描之前进行替换,如果该标识符在预处理器中已经定义,则用1替换它,否则,用0替换它。

预处理器进行宏扩展之后仍然存在的任何标识符都将用0来替换。

相关文档
最新文档