非常教程

C参考手册

C 语法

Variadic arguments

变量函数是可以用不同数量的参数调用的函数。

只有新式(原型)函数声明可能是可变的。这由...必须出现在参数列表中的最后一个格式的参数表示,并且必须至少跟随一个命名参数。

//New-style declaration
int printx(const char* fmt, ...); // function declared this way
printx("hello world"); // may be called with one
printx("a=%d b=%d", a, b); // or more arguments
 
// int printy(..., const char* fmt); // Error: ... must be the last
// int printz(...); // Error: ... must follow at least one named parameter

在函数调用中,作为变量参数列表一部分的每个参数都会经历特殊的隐式转换,称为默认参数促销。

在使用可变参数的函数体内,可以使用<stdarg.h>库函数来访问这些参数的值:

| Defined in header <stdarg.h> |

|:----|

| va_start | 允许访问可变参数函数参数(函数宏)|

| va_arg | 访问下一个可变参数函数参数(函数宏)|

| va_copy(C99)| 制作可变参数函数参数(函数宏)|的副本

| va_end | 结束可变参数函数参数(函数宏)|的遍历

| va_list | 保存va_start,va_arg,va_end和va_copy(typedef)所需的信息|

注释

虽然旧式(无原型)函数声明允许后续函数调用使用任意数量的参数,但它们不允许为可变参数(从C89开始)。这种函数的定义必须指定一个固定数量的参数,并且不能使用这些stdarg.h宏。

//old-style declaration
int printx(); // function declared this way
printx("hello world"); // may be called with one
printx("a=%d b=%d", a, b); // or more arguments
// the behavior of one of these calls is undefined, depending on
// whether the function is defined to take 1 or 3 parameters

#include <stdio.h>
#include <time.h>
#include <stdarg.h>
 
void tlog(const char* fmt,...)
{
    char msg[50];
    strftime(msg, sizeof msg, "%T", localtime(&(time_t){time(NULL)}));
    printf("[%s] ", msg);
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}
 
int main(void)
{
   tlog("logging %d %d %d...\n", 1, 2, 3);
}

输出:

[10:21:38] logging 1 2 3...

参考

  • C11标准(ISO / IEC 9899:2011):
    • 6.7.6.3/9函数声明符(包括原型)(p:133)
    • 7.16变量参数<stdarg.h>(p:269-272)
  • C99标准(ISO / IEC 9899:1999):
    • 6.7.5.3/9函数声明符(包括原型)(p:119)
    • 7.15变量参数<stdarg.h>(p:249-252)
  • C89 / C90标准(ISO / IEC 9899:1990):
    • 3.5.4.3/5函数声明符(包括原型)
    • 4.8变量<stdarg.h>

C 语法相关

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

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