va_list(),va_start(),va_arg(),va_end() 详细解析

va_list(),va_start(),va_arg(),va_end() 详细解析

这四个函数在 C 语言中常用于对函数参数数量和类型不定的情况进行处理。下面将详细解析这四个函数。

va_list

它是 C 标准库中的一个类型,通常是一个指针,指向参数列表的起始位置。它用于存储从 va_start() 开始到参数列表最后一个参数数据地址的位置。

va_start

va_start() 宏用于将 va_list 指向参数列表的起始位置。

语法如下:

void va_start(va_list ap, last);

其中,ap 是指针,指向参数列表的开始位置,last 是函数中的最后一个命名参数。

以下是一个示例:

#include <stdio.h>
#include <stdarg.h>

void printNumbers(int count, ...) {
  va_list ap;
  int i;

  va_start(ap, count); // 将ap指向第一个可变参数的地址

  for (i=0; i<count; i++) {
    int value = va_arg(ap, int); // 读取下一个int类型参数
    printf("%d ", value);
  }

  va_end(ap); // 结束时释放ap指向的内存
}

int main() {
  printNumbers(3, 1, 2, 3); // 输出 1 2 3 
  return 0;
}

在上述示例中,va_list 类型的变量 ap 是用于存储从 va_start() 开始到可变参数列表最后一个参数数据地址的位置。va_start() 的第一个参数就是 ap,第二个参数是函数中的最后一个固定参数,这里是 countva_start() 实现了 "ap = &count + sizeof(count)" 的功能,即通过传递 count 变量的地址来确定可变参数的起始地址。

va_arg

va_arg() 函数用于返回当前的可变参数,然后将 va_list 指向下一个参数。va_arg() 的原型如下:

type va_arg(va_list ap, type);

其中 ap 是使用 va_start() 初始化的 va_list 类型指针,type 是参数的类型。

以下是一个示例:

#include <stdio.h>
#include <stdarg.h>

double average(int count, ...) {
  va_list ap;
  int i;
  double sum = 0;

  va_start(ap, count);

  for (i=0; i<count; i++) {
    sum += va_arg(ap, double);
  }

  va_end(ap);

  return sum/count;
}

int main() {
  printf("Average = %f\n", average(3, 1.0, 2.0, 3.0)); // 输出 Average = 2.000000
  return 0;
}

在上述示例中, va_arg() 函数每次调用都返回可变参数列表中的下一个参数,类型由第二个参数 type 决定,同时将指向 va_list 的指针向后移动类型所占用的字节数。

va_end

va_end() 宏用于结束可变参数的获取。它接受一个 va_list 类型的参数,并清除释放在调用 va_start() 时建立的内存。

语法如下:

void va_end(va_list ap);

以下是一个示例:

#include <stdio.h>
#include <stdarg.h>

void foo(int count, ...) {
  va_list ap;
  int i;

  va_start(ap, count);

  for (i=0; i<count; i++) {
    int value = va_arg(ap, int);
    printf("%d ", value);
  }

  va_end(ap);
}

int main() {
  foo(3, 1, 2, 3); // 输出 1 2 3 
  return 0;
}

在上述示例中,va_end() 释放了 va_list 指针 ap,因此在 va_end()ap 必须重新初始化要重新使用它。

以上就是 va_list(),va_start(),va_arg(),va_end() 函数的详细解析。这些函数是处理参数列表不定的函数非常有用的工具。

示例

下面还演示一下如何使用 va_list()va_start()va_arg()va_end() 函数来实现可变参数的函数:

#include <stdio.h>
#include <stdarg.h>

int sum(int num, ...) {
  va_list valist;
  int sum = 0, i;

  va_start(valist, num);

  for (i = 0; i < num; i++)
    sum += va_arg(valist, int);

  va_end(valist);

  return sum;
}

int main() {
  printf("Sum = %d\n", sum(3, 1, 2, 3)); // 输出 Sum = 6 
  printf("Sum = %d\n", sum(4, 2, 4, 6, 8)); // 输出 Sum = 20 
  return 0;
}

在上述示例中,函数 sum() 接受任意数量的参数,并返回它们的总和。它使用了 va_list()va_start()va_arg()va_end() 函数来处理不定数目的参数列表,其中 va_start() 用于初始化 va_list 中的变量,va_arg() 用于按顺序访问每个参数,va_end() 用于清理内存。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:va_list(),va_start(),va_arg(),va_end() 详细解析 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • 详解Android JNI的基本使用(CMake)

    下面我来详细讲解一下“详解Android JNI的基本使用(CMake)”的完整攻略。 什么是 JNI JNI(Java Native Interface)是Java提供的一套编程规范,用于在Java和C/C++之间进行互操作。通过使用JNI,我们可以在Java代码中调用C/C++实现的函数,并且可以将Java对象转换为C/C++中对应的数据类型,实现跨语言…

    C 2023年5月23日
    00
  • 魔兽世界H黑石铸造厂武僧T心得分享

    魔兽世界H黑石铸造厂武僧T心得分享 简介 魔兽世界H黑石铸造厂(Blackrock Foundry)是一项难度较高的副本任务,需要玩家掌握高级操作技巧和相应战术,才能完成。本文介绍了在该副本中,武僧T队员的心得体会和策略分享。具体内容如下: 副本简介 H黑石铸造厂副本一共有10个大Boss,其中武僧T团队需要面对的有:- 炉渣工匠- 爆裂熔炉- 钢铁女武神-…

    C 2023年5月22日
    00
  • C 简介

    我非常乐意为您提供关于“C 简介”的完整使用攻略。 一、概述 C语言是一种功能强大且广泛使用的编程语言。它通常被用于系统编程、驱动程序开发和高性能应用程序中。C语言在计算机科学教育中也是一种非常常见和重要的编程语言。 在这篇“C 简介”的文章中,我们将介绍C语言的基本概念和语法,例如变量、运算符、条件控制语句、循环语句等。阅读完本文后,您将对C语言有一个基本…

    C 2023年5月10日
    00
  • 关于C语言多线程pthread库的相关函数说明

    关于C语言多线程pthread库的相关函数说明,我会分为以下几个部分进行讲解: 1. 前言 在讲解多线程pthread库的相关函数说明之前,我们需要了解一下线程的相关概念。 线程是操作系统中的一种执行单元,是处理器调度的基本单位。相对于进程,线程更加轻量级,可以并发执行,一个进程可以包含多个线程。线程之间可以共享代码段、数据段和系统资源。多线程编程可以提高程…

    C 2023年5月23日
    00
  • C语言实现病例管理系统

    C语言实现病例管理系统攻略 1. 简介 病例管理系统是医院或诊所等医疗机构常用的一种信息管理系统,通过该系统能够快速有效地管理病人的基本信息、病史以及药物处方等。这需要使用到C语言的数据类型、字符串操作等基本操作,实现起来比较简单。 2. 实现流程 2.1 确定需求 首先,我们需要明确病例管理系统需要具备哪些功能,如:添加病例、删除病例、修改病例、查询病例等…

    C 2023年5月23日
    00
  • 各种加密方案分析

    各种加密方案分析 概述 在网络通信中,加密方案是保证数据机密性与完整性的重要手段,目前常用的加密方案包括对称加密与公钥加密。本文将对各种加密方案进行详细的分析与评估,并提供一些实例说明。 对称加密 对称加密算法是指加密方与解密方使用同样的密钥来加密解密数据的一种加密方法,常见的对称加密算法包括DES、AES等。对称加密算法的优势在于加解密速度快,但其中密钥交…

    C 2023年5月22日
    00
  • 剑网3明教怎么玩_剑网3明教贯木流PVE输出攻略(必看)

    剑网3明教怎么玩 简介 《剑网3》作为一款以武学为主题的MMORPG游戏,拥有多个门派供玩家选择。其中明教门派以其独树一帜的特点,备受玩家们的喜爱。本攻略将为大家介绍明教门派的PVE输出攻略,帮助各位玩家更好地在游戏中玩转明教职业。 明教门派的特点 明教门派主修内功心法,拥有较高的爆发输出和回复能力 明教的操作非常流畅,配合技能后摇短,能够进行多种连招输出 …

    C 2023年5月22日
    00
  • C++基本算法思想之递推算法思想

    C++基本算法思想之递推算法思想 什么是递推算法 递推算法又称为递归算法,是常用于求解问题的一种算法思想。它通过求出问题的一个基本情况,然后通过逐步迭代、递推,从而得到问题的一个规模更大的解。通俗的说,就是将一个大问题分解成多个相对较小的问题,通过依次解决每个小问题最终得到大问题的解。 如何实现递推算法 递推算法可以通过编写递归代码进行实现,也可以通过循环实…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部