• C语言可变参数函数及其实现


    概述

    本文讨论C语言中的可变参数函数,特别关注printf和scanf,它们允许根据需要确定参数的个数。这篇文章还介绍了可变参数函数的实现细节和相关宏

    1. 可变参数函数的概念

    C语言引入了可变参数函数的概念,允许函数的参数个数根据需要确定。这对于函数如printf和scanf非常有用。

    2. 可变参数函数的实现方式

    这些不定参数函数通过堆栈方式实现,尽管理论上参数个数没有限制,但实际上由于内存或栈的大小限制,参数个数是有上限的。当达到上限时,会出现错误。

    3. 函数宏

    C语言提供了一些宏来帮助实现可变参数函数,主要包括:

    VA_LIST:用于处理可变参数的宏,需要包含 头文件。
    INTSIZEOF:用于获取类型占用的空间长度,通常是int的整数倍。
    VA_START:用于获取可变参数列表的第一个参数的地址。
    VA_ARG:用于获取可变参数的当前参数,根据参数的类型返回值,并将指针指向下一个参数。
    VA_END:用于清空可变参数列表。

    4. 使用方法

    在使用可变参数函数时,遵循以下步骤:

    (1)在函数内部定义一个VA_LIST型的变量,这个变量是指向参数的指针。

    (2)使用VA_START宏初始化刚定义的VA_LIST变量。

    (3)使用VA_ARG宏获取可变的参数,根据参数的类型获取值,并使指针指向下一个参数。

    (4)使用VA_END宏结束可变参数的获取。

    5. 示例

    #include 
    
    #include 
    
    #include
    
    void my_printf(const char* fmt, ...)
    {
        va_list ap;                  //在函数内部定义一个VA_LIST型的变量,这个变量是指向参数的指针。
        va_start(ap, fmt);           //使用VA_START宏初始化刚定义的VA_LIST变量。
        for (; *fmt; ++fmt)          //for循环处理补丁参数
        {
            if (*fmt != '%')
            {
                putchar(*fmt);
                continue;
            }
            ++fmt;
            if ('\0' == *fmt)
            {
                assert(0);
                break;
            }
            switch (*fmt)
            {
                case '%':
                    putchar('%');
                    break;
                case 'd':
                {
                    int i = va_arg(ap, int);    //使用VA_ARG宏获取可变的参数,根据参数的类型获取值,并使指针指向下一个参数。
                    printf("%d", i);
                }
                break;
                case 'c':
                {
                    char c = va_arg(ap, char);
                    printf("%c", c);
                }
                break;
            }
        }
        va_end(ap);     //使用VA_END宏结束可变参数的获取
    }
    
    
    int main() {
        my_printf("Hello, World!\n");
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
  • 相关阅读:
    燃气智能巡检系统-燃气入户安检系统
    Excel求和公式的几种用法
    ffmpeg MP4转YUV格式保存
    Proteus仿真--花样流水灯(仿真文件+程序)
    RibbitMQ学习笔记之交换机实战
    【红外与可见光图像融合】离散平稳小波变换域中基于离散余弦变换和局部空间频率的红外与视觉图像融合方法(Matlab代码实现)
    巨头游戏:Instagram 将运行 Polygon 支持的 NFT 市场
    阿里云服务器修改IP地址的两种方法
    论文解读(GCC)《GCC: Graph Contrastive Coding for Graph Neural Network Pre-Training》
    vue 项目代码架构
  • 原文地址:https://blog.csdn.net/Aviciit/article/details/133985936