可变参数 函数(可变参列表—2) 实现小型日志文件

C/C++可变参数列表参数处理方法va_list、va_start()、va_copy()、va_arg()、va_end() C/C++可变参数列表的处理方法 阅读详情
 va_list arg_ptr:定义一个指向个数可变的参数列表指针;
  
  va_start(arg_ptr, argN):使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一个固定参数;…之前的一个参数),函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。如果有一va函数的声明是void va_test(char a, char b, char c, …),则它的固定参数依次是a,b,c,最后一个固定参数argN为c,因此就是va_start(arg_ptr, c)。
  
  va_arg(arg_ptr, type):返回参数列表中指针arg_ptr所指的参数,返回类型为type,并使指针arg_ptr指向参数列表中下一个参数。
  
  va_copy(dest, src):dest,src的类型都是va_list,va_copy()用于复制参数列表指针,将dest初始化为src。
  
  va_end(arg_ptr):清空参数列表,并置参数指针arg_ptr无效。说明:指针arg_ptr被置无效后,可以通过调用va_start()、va_copy()恢复arg_ptr。每次调用va_start() / va_copy()后,必须得有相应的va_end()与之匹配。参数指针可以在参数列表中随意地来回移动,但必须在va_start() … va_end()之内。
  
  
  
  ◎用法:
  func( Type para1, Type para2, Type para3, ... )
  {
   /****** Step 1 ******/
   va_list ap;
   va_start( ap, para3 ); //一定要“...”之前的那个参数
   
   /****** Step 2 ******/
   //此时ap指向第一个可变参数
   //调用va_arg取得里面的值
   
   Type xx = va_arg( ap, Type ); 
   
   //Type一定要相同,如:
   //char *p = va_arg( ap, char *);
   //int i = va_arg( ap, int );
  
   //如果有多个参数继续调用va_arg
  
   /****** Step 3 ******/
   va_end(ap); //For robust!
  }
  
  ◎研究:
  typedef char * va_list;
  
  #define va_start _crt_va_start
  #define va_arg _crt_va_arg
  #define va_end _crt_va_end
  
  #define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
  #define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
  #define _crt_va_end(ap) ( ap = (va_list)0 ) 
  va_list argptr;
  C语言的函数是从右向左压入堆栈的,调用va_start后,
  按定义的宏运算,_ADDRESSOF得到v所在的地址,然后这个
  地址加上v的大小,则使ap指向第一个可变参数如图: 
   
   栈底 高地址
   | ....... 
   | 函数返回地址
   | ....... 
   | 函数最后一个参数
   | .... 
   | 函数第一个可变参数 <--va_start后ap指向 
   | 函数最后一个固定参数
   | 函数第一个固定参数 

   栈顶 低地址

通过可变参数实现可变参数的项目日志输出

需包含头文件头文件

#ifndef LOG_PRINTF_H
#define LOG_PRINTF_H

#include <stdio.h>
#include <time.h>
#include <stdarg.h>
#define  ISPRINTF 1
#define  LOGFILE "D:\\Projectlog.txt"
bool LogPrintf(const char* pFormat,...)
{

	if(ISPRINTF)
	{
		time_t nTime;
		struct tm *tmDateTime;
		char sDateTime[6][16];
		FILE *pfile = NULL;

		char Buffer[512];
		va_list args;
		va_start(args, pFormat);
		vsprintf(Buffer,pFormat,args);
		va_end( args );

		if (NULL == Buffer) return(0);
		time(&nTime);
		tmDateTime = (struct tm*) localtime(&nTime);
		pfile = fopen(LOGFILE, "a+");
		if (!pfile) return(0);

		strftime(sDateTime[0], 16, "%m", tmDateTime);
		strftime(sDateTime[1], 16, "%d", tmDateTime);
		strftime(sDateTime[2], 16, "%Y", tmDateTime);
		strftime(sDateTime[3], 16, "%H", tmDateTime);
		strftime(sDateTime[4], 16, "%M", tmDateTime);
		strftime(sDateTime[5], 16, "%S", tmDateTime);

		fprintf(pfile, "[%s/%s/%s %s:%s:%s]", sDateTime[2],sDateTime[0] ,sDateTime[1] , sDateTime[3], sDateTime[4], sDateTime[5]);
		fprintf(pfile, "%s\n",Buffer);

		if (pfile != NULL) 
			fclose(pfile);
		return 1;
	}
	else
		return false;
}
#endif

使用

#include "LogPrintf.h"
#include <iostream>
using namespace std;
#define  ISPRINTF 0 //定义是否打印
int main()
{
	LogPrintf("%s","logfile have been build succeed!");
	return 0;
}


从日志文件读懂你的LAMMPS仿真:一份给计算材料新手的性能分析解读手册 本文为计算材料新手提供了一份详细的LAMMPS分子动力学仿真日志文件解读手册。通过解析日志结构、分析性能指标(如CPU利用率、时间分解)和提供实战优化策略(如Pair计算优化、Kspace加速),帮助用户从基础运行进阶到高效优化,显著提升仿真效率。 阅读详情

相关推荐

nweb_nweb:小型安全的Web服务器(仅静态页面)

您是否曾经想过运行一个小型,安全的Web服务器,而不必担心使用安装和配置可能很复杂的功能强大的Web服务器? 您是否想知道如何编写一个通过网络套接字接收传入消息的程序? 您是否曾经希望自己的Web服务器进行试验和学习? 2012年将进行进一步更新,以支持最新的Web服务器和浏览器标准以及代码更新。 好吧,别无所求-nweb是您所需要的。 这是一个只有200行C源代码的简单Web服务器。 它...

cusi77914的博客 1332

C语言可变参数原理

在了解可变参数之前,我们先了解下函数调用惯例,这个对于入栈的理解非常重要。也是奠定了可变参数能够实现的基础。 函数调用惯例 调用惯例 清理方 参数传递顺序 函数编译后修饰规则 cdecl 函数调用方 从右到左的顺序压栈 下划线+函...

yexiang优快云的专栏 3864

CAN-do-paser:Java开发的CAN总线数据帧解析库

CAN总线数据帧使用DBC文件信息解析为物理量,基于Java开发的数据解析工具。

佳瑞的博客 1133

va_list,va_start,va_arg,va_copy和va_end的使用

va_list arg_ptr:定义一个指向个数可变的参数列表指针; va_start(arg_ptr, argN):使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一个固定参数;…之前的一个参数),函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。如果有一va函数的声明是void va_test(

garygeeker的专栏 2448

STM32H750实战:如何用CubeMX配置NAND Flash时序(附常见问题排查)

本文详细解析了STM32H750通过CubeMX配置NAND Flash时序的实战技巧,包括硬件连接、时序参数计算与优化策略,以及常见问题如RGB屏幕干扰、多片选冲突的解决方案。特别针对NAND Flash的时序配置和抗干扰设计提供了实用代码示例和优化建议,帮助开发者提升系统稳定性和性能。

weixin_29176179的博客 363

30分钟搭建AI科研写作工作台:基于WorkBuddy的论文全流程加速实践

在人工智能技术日益普及的今天,如何利用智能工具提升专业领域工作效率成为关键课题。其核心原理在于通过模块化设计,将复杂的任务流程拆解为可复用、可编排的标准化技能单元,并结合精准的指令控制,实现从通用对话到深度任务执行的转变。这一技术价值在于显著降低重复性劳动强度,将人的创造力聚焦于核心决策与创新环节。在科研写作、数据分析、代码开发等场景中,这类智能工作台能有效辅助完成文献调研、内容生成、格式校验等繁琐步骤。本文以科研论文写作为具体应用场景,深入探讨如何利用WorkBuddy这一智能工作台,通过配置核心科研技能

weixin_29032489的博客 1486

C语言函数大全-- v 开头的函数

本篇介绍 C 语言中的 v 开头的函数

Huazie 3305

手把手教你用STM32的ADC读取PT100模块,实现高精度温度采集(附完整代码)

本文详细介绍了如何利用STM32的ADC模块读取PT100温度传感器信号,实现高精度温度采集系统。从硬件选型、ADC配置校准到温度计算算法和软件滤波技术,提供完整的实现方案和优化技巧,帮助工程师快速构建稳定可靠的温度监测系统。

weixin_29185199的博客 345

va_start、va_end、va_list的使用

以前的那篇讲的不好,添加一篇新的 http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html va_start和va_end使用详解   本文主要介绍va_start和va_end的使用及原理。   在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end这

sunshine_okey的专栏 2021

NSGA-III相关笔记

NSGA-III目录目的区别NSGA-III的算法流程非支配排序详解归一化详解 目录 NSGA-III基于matlab的实现 参考文献 1.An Evolutionary Many-Objective Optimization Algorithm Using Reference-point Based Non-dominated Sorting Approach,Part I: Solving P...

weixin_42555400的博客 1万+

数电实验,如何安装Quartus II软件?

数电实验第一步,安装软件Quartus II! 安装这个软件可以说是很折磨我了,依然是failed很多次之后终于可以了! 能成功安装,多亏了网络上的各路大神!!!不胜感激 现在分享经验如下: ps:我分享的是Quartus II 14.0版本的软件及破解器安装使用方法 注意!想要在电脑上顺利安装,前提条件是电脑有10G以上内存!!! 友情提示:建议整个下载过程中,提前关掉所有杀毒、电脑

一个程序媛的成长记录❤ 3655

Python 计算日志文件中的错误率统计

通过本文介绍的方法,我们可以轻松地使用 Python 对日志文件进行分析,并得出有用的错误率指标。这种方法不仅适用于小型项目,也能很好地扩展到大型分布式系统中。```

2501_91114657的博客 993

MATLAB - 使用 RRT 进行挖掘机运动规划

本例演示了如何使用运动规划器在包含障碍物的环境中为挖掘机规划路径。在此示例中,您将以运动树的简化形式为挖掘机建模,然后使用基于采样的运动规划器确定挖掘机在存在障碍物的两个姿势之间的可行路径。在 Simscape™ 多体™ 模型中模拟结果。

机器人控制与仿真应用 1850

Python函数全解析:从基础语法到高阶应用与最佳实践

函数是编程语言中实现代码复用和逻辑封装的核心概念,其本质是将特定功能封装为可重复调用的代码单元。理解函数的参数传递机制、作用域和返回值原理,是构建模块化、可维护软件的基础。在工程实践中,函数的高阶应用如装饰器、闭包和生成器,能显著提升代码的灵活性和效率,尤其适用于Web开发、数据分析和自动化脚本等场景。本文以Python为例,深入探讨了装饰器如何在不修改源码的情况下增强函数能力,以及生成器函数如何利用yield关键字实现惰性计算以优化内存使用,帮助开发者从“会用”进阶到“精通”,打造更健壮、优雅的代码。

weixin_30254435的博客 329

通信算法之283:大疆DJI云哨系统-DJI DroneID物理层协议-解速率匹配及Turbo译码

3. 完整云哨接收机,接收灵敏度。交流: 1279682290 ,2. Turbo译码模块。1. 解速率匹配模块。

leegang12的专栏 868

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

操作系统调试

调试是发现计算机系统中的问题并解决它们的过程。操作系统执行调试的方式有很多种。其中一些是 -

新华编程特战队 99

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Python高级语法精讲:从Pythonic编程到实战性能优化

Python作为一门高级编程语言,其核心魅力在于简洁优雅的语法设计和强大的表达能力。理解Python的底层原理,如生成器表达式、上下文管理器等,是编写高效、可维护代码的关键。这些特性不仅提升了代码的执行效率,还增强了程序的可读性和健壮性,在数据处理、Web开发、自动化脚本等工程实践中价值显著。本文聚焦于Python开发中的常用语法,深入探讨列表推导式、字典操作、函数参数解包等核心概念,并结合海象运算符、f-string等现代语法特性,通过实战案例展示如何运用这些知识解决真实问题,帮助开发者从‘能用’迈向‘优

weixin_30321449的博客 493

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Python列表数据清洗:高效删除空白与指定元素的四种方法与实践

在数据处理与清洗中,列表(list)作为Python核心数据结构,常因包含空值、无效占位符等杂质而影响分析结果。其原理在于通过条件筛选机制,区分原地修改与创建新列表两种操作模式,以平衡内存与安全性。技术价值体现在提升代码的简洁性、可维护性与执行效率,是数据预处理的关键环节。应用场景广泛,涵盖从API接口、日志文件解析到数据库记录清洗等日常开发任务。本文聚焦于使用列表推导式、filter()函数等Pythonic工具,一次性解决删除None、空字符串等空白元素及指定元素的痛点,并深入探讨了处理嵌套结构、海量数

weixin_30236595的博客 445

LFM2-2.6B-GGUF快速上手:VS Code插件集成实现代码内直接调用AI服务

本文介绍了如何在星图GPU平台上自动化部署Liquid AI公司开发的LFM2-2.6B-GGUF大语言模型镜像,并通过VS Code插件集成实现代码内直接调用AI服务。该方案特别适用于开发者快速获取代码补全、文档生成等智能辅助功能,显著提升编程效率。

weixin_33557333的博客 765

调试C语言程序-使用日志的方式

1自定义日志调试 1-1引入 #include <stdio.h> int fact(int n){ int i,f=1; for( i=1; i<=n; i++){ f += i; } return f; } int main(){ printf( "4!=%d\n", fact(4) ); return 0; } 输出结果为:4!=11 与预期的结果不同,因此我们要对程序进行调试 我们在调试程序时,输出调试信息(又称为”打

weixin_42534168的博客 552

Python列表反转:四种方法原理、性能对比与实战场景全解析

在Python编程中,列表(List)作为核心数据结构,其元素顺序操作是数据处理的基础。反转列表操作通过改变索引映射关系实现,涉及算法效率与内存管理原理。掌握不同反转方法的技术价值在于能根据场景优化性能与资源,例如在内存敏感的大数据处理或需要保留原数据的业务逻辑中做出合适选择。本文聚焦切片操作 `[::-1]`、`reversed()` 迭代器、`reverse()` 原地方法及手动循环四种核心方案,深入剖析其底层机制与适用边界,并结合**嵌套列表反转陷阱**与**超大列表内存优化**等高频问题,提供从基础

weixin_34221775的博客 375

操作系统调试方法

调试是发现计算机系统中的问题并解决它们的过程。操作系统执行调试的方式有很多种。

新华编程特战队 165

Python列表反转四种方法详解:从reverse()到切片[::-1]的性能与应用场景

列表是Python中最核心的数据结构之一,其反转操作在数据处理、算法实现和游戏开发等场景中极为常见。从原理上讲,列表反转涉及元素顺序的逆序排列,不同的实现方式在内存管理和时间复杂度上存在显著差异。掌握高效的反转技术,能提升代码性能与可读性,尤其在处理大规模数据时至关重要。在Python中,常用的反转方法包括原地修改的reverse()方法、返回迭代器的reversed()函数、简洁直观的切片语法[::-1]以及手动遍历实现。例如,在游戏开发中,反转角色队列或排行榜顺序时,需根据是否保留原数据、内存敏感度等因

weixin_30596343的博客 299

Python map函数实战指南:高效处理序列变换的日常利器

map函数是Python中实现‘对序列中每个元素应用同一操作’这一基础编程范式的标准工具,其核心原理是建立输入与输出间的声明式映射契约,而非过程式控制。它依托迭代器协议,天然支持内存友好的流式处理,并与lambda、内置函数(如int、str.upper)及operator模块深度协同,显著提升数据清洗、ETL流水线和批量格式转换等场景的代码简洁性与可维护性。相比列表推导式,map在大数据量、强调不可变性与函数式组合(如map+filter+reduce)时具备独特优势。本文结合真实电商订单清洗案例,详解其

weixin_30856725的博客 377

Nginx之日志拆分-yellowcong

日志对于网站来说,非常的重要,通常日志的处理有两种,一种是Hadoop离线处理,还有就是通过storm实现实时计算分析处理,但是日志过大,需要我们写脚本进行拆分日志文件。小型网站,一天已备份,就够了。对于大网站,可能一小时一备份 时间函数 #日期函数,获取昨天时间 ...

chengkuiwu3328的博客 173
上一篇: 初谈内核对像-01
下一篇: 可变参数 函数(可变参数列表--1)
雪岢奇
博客等级 码龄17年 310粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值