非常教程

C参考手册

C 语法

#define directive

预处理器支持文本宏替换和类似功能的文本宏替换。

句法

#define identifier replacement-list(optional)

(1)

#define identifier( parameters ) replacement-list

(2)

#define identifier( parameters, ... ) replacement-list

(3)

(since C99)

#define identifier( ... ) replacement-list

(4)

(since C99)

#undef identifier

(5)

说明

#define 指令

#define指令定义的标识符作为一个宏,即它们指示编译器替换替换列表标识符的所有连续出现,其可以额外地任选地进行处理。如果标识符已经被定义为任何类型的宏,那么该程序是格式不正确的,除非定义相同。

类似于对象的宏

类似于对象的宏将每个定义的标识符替换为替换列表。#define指令的版本(1)的行为完全如此。

函数式的宏

类似功能的宏将替换列表中的每个出现的已定义标识符替换为另外的一些参数,然后替换替换列表中任何参数的相应出现。

函数式宏调用的语法类似于函数调用的语法:宏名称的每个实例后跟一个(作为下一个预处理标记引入由替换列表替换的标记序列)序列由匹配)令牌终止,跳过中间匹配的左右括号对。

参数的数量必须与宏定义(参数)中参数的数量相同或程序不合格。如果标识符不是功能符号,也就是说本身没有括号,它根本不会被替换。

#define指令的版本(2)定义了一个简单的函数式宏。

#define指令的版本(3)定义了一个具有可变数量参数的函数式宏。可以使用__VA_ARGS__标识符访问附加参数,然后使用标识符来替换标识符,然后使用标识符替换它们。

#define指令的版本(4)定义了一个类似函数的宏,其中包含可变数量的参数,但没有常规参数。只能使用__VA_ARGS__标识符访问参数,然后使用标识符替换标识符,并将标识符替换。

注意:如果类似函数的宏的参数包含未被左右括号(如macro(array[x = y, x + 1]))的匹配对保护的逗号,则逗号将被解释为宏参数分隔符,导致由于参数计数不匹配导致的编译失败。

# and ## operators

在函数式宏中,#替换列表中的标识符之前的运算符通过参数替换运行标识符,并将结果封装在引号中,从而有效地创建字符串文字。另外,预处理器会添加反斜杠以避免嵌入的字符串文字(如果有的话)引用,并在必要时将字符串中的反斜杠加倍。所有前导空白和尾随空白都被删除,并且文本中间的任何空白序列(但不在嵌入的字符串文字内)被折叠为单个空格。这个操作被称为“串化”。如果字符串化的结果不是有效的字符串,则行为是未定义的。

当#在__VA_ARGS__之前出现时,整个展开的__VA_ARGS__用引号引起来:#define showlist(...)puts(#__ VA_ARGS__)showlist(); //展开为puts(“”)showlist(1,“x”,int); //展开为puts(“1,\”x \“,int”)

(自C99以来)

##在替换列表中的任何两个连续标识符之间的运算符运行两个标识符上的参数替换,然后连接结果。这个操作被称为“连接”或“令牌粘贴”。只有形成一个有效令牌的令牌可以被粘贴:形成一个更长的标识符的标识符,形成一个数字的数字,或运算符,+=形成一个+=。评论不能通过粘贴来创建,/并且*因为在考虑宏替换之前从文本中删除评论。如果连接的结果不是有效的标记,则行为是未定义的。

注意:有些编译器提供了一个允许##出现在逗号之后和__VA_ARGS__之前的扩展,在这种情况下,当__VA_ARGS__非空时,##什么也不做,但当__VA_ARGS__为空时删除逗号:这使得可以定义宏等fprintf (stderr, format, ##__VA_ARGS__)

#undef directive

#undef指令取消定义标识符,即它通过#define指令取消标识符的先前定义。如果标识符没有关联的宏,则该指令被忽略。

预定义的宏

任何翻译单元中都预先定义了以下宏名称:

__STDC__

expands to the integer constant 1. This macro is intended to indicate a conforming implementation (macro constant)

__STDC_VERSION__ (C95)

expands to an integer constant of type long whose value increases with each version of the C standard: 199409L (C95) 199901L (C99) 201112L (C11) (macro constant)

__STDC_HOSTED__ (C99)

expands to the integer constant 1 if the implementation is hosted (runs under an OS), ​0​ if freestanding (runs without an OS) (macro constant)

__FILE__

expands to the name of the current file, as a character string literal, can be changed by the #line directive (macro constant)

__LINE__

expands to the source file line number, an integer constant, can be changed by the #line directive (macro constant)

__DATE__

expands to the date of translation, a character string literal of the form "Mmm dd yyyy". The name of the month is as if generated by asctime and the first character of "dd" is a space if the day of the month is less than 10 (macro constant)

__TIME__

expands to the time of translation, a character string literal of the form "hh:mm:ss", as in the time generated by asctime() (macro constant)

  • 199409L (C95)
  • 199901L (C99)
  • 201112L (C11) (macro constant)
 \_\_STDC\_HOSTED\_\_

(C99)

1如果实施托管(在 OS 下运行),​0​则 扩展为整数常量,如果是独立的(无 OS 的情况下运行)

(macro constant) __FILE__

扩展为当前文件的名称,作为字符串文字,可以通过#line 指令进行更改

(macro constant) __LINE__

展开为源文件行号,一个整数常量,可以通过#line 指令进行更改

(macro constant) __DATE__

扩展到翻译日期,形式为 “Mmm dd yyyy” 的字符串文字。月份的名称如同生成的一样,如果asctime月份的日期小于10,则“dd”的第一个字符是空格

(macro constant) __TIME__

扩展到翻译时,形式为 “hh:mm:ss” 形式的字符串文字,如在 asctime()

(macro constant)

以下附加宏名称可能由实现预定义:

__STDC_ISO_10646__ (C99)

expands to an integer constant of the form yyyymmL, if wchar_t uses Unicode, the date indicates the latest revision of Unicode supported (macro constant)

__STDC_IEC_559__ (C99)

expands to 1 if IEC 60559 is supported (macro constant)

__STDC_IEC_559_COMPLEX__ (C99)

expands to 1 if IEC 60559 complex arithmetic is supported (macro constant)

__STDC_UTF_16__ (C11)

expands to 1 if char16_t use UTF-16 encoding (macro constant)

__STDC_UTF_32__ (C11)

expands to 1 if char32_t use UTF-32 encoding (macro constant)

__STDC_MB_MIGHT_NEQ_WC__ (C99)

expands to 1 if wide character encoding of the basic character set may not equal their narrow encoding, such as on EBCDIC-based systems that use Unicode for wchar_t (macro constant)

__STDC_ANALYZABLE__ (C11)

expands to 1 if analyzability is supported (macro constant)

__STDC_LIB_EXT1__ (C11)

expands to an integer constant 201112L if bounds-checking interfaces are supported (macro constant)

__STDC_NO_ATOMICS__ (C11)

expands to 1 if atomic types and atomic operations library are not supported (macro constant)

__STDC_NO_COMPLEX__ (C11)

expands to 1 if complex types and complex math library are not supported (macro constant)

__STDC_NO_THREADS__ (C11)

expands to 1 if multithreading is not supported (macro constant)

__STDC_NO_VLA__ (C11)

expands to 1 if variable-length arrays are not supported (macro constant)

这些宏的值(除了__FILE____LINE__)在整个翻译单元中保持不变。尝试重新定义或取消定义这些宏会导致未定义的行为。

预定义变量__func__(详见函数定义)不是预处理器宏,即使它有时与__FILE__和__LINE__一起使用,例如通过 assert。

(自C99以来)

#include <stdio.h>
 
//make function factory and use it
#define FUNCTION(name, a) int fun_##name(int x) { return (a)*x;}
 
FUNCTION(quadruple, 4)
FUNCTION(double, 2)
 
#undef FUNCTION
#define FUNCTION 34
#define OUTPUT(a) puts( #a )
 
int main(void)
{
    printf("quadruple(13): %d\n", fun_quadruple(13) );
    printf("double(21): %d\n", fun_double(21) );
    printf("%d\n", FUNCTION);
    OUTPUT(million);               //note the lack of quotes
}

输出:

quadruple(13): 52
double(21): 42
34
million

参考

  • C11标准(ISO / IEC 9899:2011):
    • 6.10.3宏替换(p:166-173)
    • 6.10.8预定义的宏名称(p:175-176)
  • C99标准(ISO / IEC 9899:1999):
    • 6.10.3宏替换(p:151-158)
    • 6.10.8预定义的宏名称(p:160-161)
  • C89 / C90 标准(ISO / IEC 9899:1990):
    • 3.8.3宏替换
    • 3.8.8预定义的宏名称

C 语法相关

1.#elif directive
2.#else directive
3.#endif directive
4.#error directive
5.#if directive
6.#ifdef directive
7.#ifndef directive
8.#include directive
9.#line directive
10.#pragma directive
11.alignas
12.Alternative operators and tokens
13.Analyzability
14.Arithmetic operators
15.Arithmetic types
16.Array declaration
17.Array initialization
18.ASCII Chart
19.Assignment operators
20. types
21.Basic concepts
22.Bit fields
23.break statement
24.C language
25.C Operator Precedence
26.cast operator
27.character constant
28.Comments
29.Comparison operators
30.compound literals
31.Conditional inclusion
32.Conformance
33.const type qualifier
34.Constant expressions
35.continue statement
36.Declarations
37.do-while loop
38.Enumerations
39.Escape sequences
40.Expressions
41.External and tentative definitions
42.File scope
43.floating constant
44.for loop
45.Function declarations
46.Function definitions
47.Functions
48.Generic selection
49.goto statement
50.Identifier
51.if statement
52.Implicit conversions
53.Increment/decrement operators
54.Initialization
55.inline function specifier
56.integer constant
57.Lifetime
58.Logical operators
59.Lookup and name spaces
60.Main function
61.Member access operators
62.Memory model
63.Objects and alignment
64.Order of evaluation
65.Other operators
66.Phases of translation
67.Pointer declaration
68.Preprocessor
69.restrict type qualifier
70.return statement
71.Scalar initialization
72.Scope
73.sizeof operator
74.Statements
75.static assert declaration
76.Static storage duration
77.Storage-class specifiers
78.string literals
79.Struct and union initialization
80.Struct declaration
81.switch statement
82.Thread storage duration
83.Type
84.Type
85.Typedef declaration
86.Undefined behavior
87.Union declaration
88.Value categories
89.Variadic arguments
90.volatile type qualifier
91.while loop
92._Alignof operator
93._Noreturn function specifier
C

C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。