扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
#include "stdarg.h"
正宁网站制作公司哪家好,找成都创新互联公司!从网页设计、网站建设、微信开发、APP开发、响应式网站开发等网站项目制作,到程序开发,运营维护。成都创新互联公司于2013年开始到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联公司。
//n表示输入参数,总的个数,后面是各个元素的值
int va_add(int n,...)
{
va_list lst;
int i;
int t = 0;
va_start(lst,n);
for (i = 0; i n; i++)
{
int c = va_arg(lst, int);
printf("%d: %d\n", c);
t += c;
}
return t;
}
int main()
{
int t = va_add(4,1,2,3,4);
printf("Sum is:%d\n", t);
getch();
return 0;
}
说的有点混乱,提供几个方法。1,你的WHILE另开一个线程.2做一个LIST保存每个LOG的信息,每个信息是NEW出来的。
说实话,我还是没明白你补充的意思。
我写个伪代码吧,希望能有点启发
list LOG_INFO* info_list;
while ()
{
...//some function
//new出来的东西在堆上,不会被释放掉,所以一直都存在
LOG_INFO* log_info = new LOG_INFO();
//放到炼表里保存指针
info_list.push_back(log_info);
...//some function
}
output_log(info_list);//把炼表给输出的函数
release_info(info_list);//释放new的东西。
基本是这个意思,就是你new出来的东西不会被释放.
另外log_info可以是一个类,里面变的东西都可以设置,当然有的东西没有可以不设置.因为具体问题不清楚,所以可能更优化.
而输出的时候是根据类里面的成员变量进行输出的.
举例:
比如可能输出的是字符串也可能输出图片那么可以定义如下
class Info
{
string str;
Image image;
bool is_str;
bool is_image;
}
然后判断到底有什么,当然也可以用指针等其他方法进行数据结构的优化.
/*
*printf.c - print formatted
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines printf() - print formatted data
*
*******************************************************************************/
#include cruntime.h
#include stdio.h
#include dbgint.h
#include stdarg.h
#include file2.h
#include internal.h
#include mtdll.h
/***
*int printf(format, ...) - print formatted data
*
*Purpose:
* Prints formatted data on stdout using the format string to
* format data and getting as many arguments as called for
* Uses temporary buffering to improve efficiency.
* _output does the real work here
*
*Entry:
* char *format - format string to control data format/number of arguments
* followed by list of arguments, number and type controlled by
* format string
*
*Exit:
* returns number of characters printed
*
*Exceptions:
*
*******************************************************************************/
int __cdecl printf (
const char *format,
...
)
/*
* stdout 'PRINT', 'F'ormatted
*/
{
va_list arglist;
int buffing;
int retval;
va_start(arglist, format);
_ASSERTE(format != NULL);
#ifdef _MT
_lock_str2(1, stdout);
__try {
#endif /* _MT */
buffing = _stbuf(stdout);
retval = _output(stdout,format,arglist);
_ftbuf(buffing, stdout);
#ifdef _MT
}
__finally {
_unlock_str2(1, stdout);
}
#endif /* _MT */
return(retval);
}
首先先看到main函数中的不定参数:
1.引用:在Turbo C2.0启动过程中, 传递main()函数三个参数: argc, argv和env。
* argc: 整数, 鴐ain()的命令行参数个数。
* argv: 字符串数组。
argv[0] 为程序运行的全路径名
argv[1] 为在DOS命令行中执行程序名后的第一个字符串;
argv[2] 为执行程序名后的第二个字符串;
...
argv[argc]为NULL。
*env: 字符串数组。env[] 的每一个元素都包含ENVVAR=value形式的字符
串。其中ENVVAR为环境变量。value 为ENVVAR的对应值
#include stdlib.h
#include stdio.h
main(int argc, char *argv[], char *env[])
{
int i;
printf("%d\n", argc); /* 为什么它的输出是 1, 它到底是定义什么的,我看不明上面的解释*/
for(i=0; i=argc; i++)
printf("argv[%d]:%s\n", i, argv[i]);
for(i=0; env[i]!=NULL; i++)
printf(" env[%d]:%s\n", i, env[i]);
}
argc, argv, env是在main()函数之前被赋值的,编译器生成的可执行文件,main()不是真正的入口点,而是一个标准的函数,这个函数名与具体的操作系统有关。
就想到其他函数是否能实现一样的功能,查询了相关资料,基本上都是利用STDARG.H中的
#define va_start(ap, parmN) (ap = ...)
#define va_arg(ap, type) (*((type *)(ap))++)
#define va_end(ap)
定义如下:
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 )
修改他人程序如下:
void average(int first,...)
{int i=first;
va_list maker;
va_start(maker,first);
while(i!=-1){ printf("%p: %d\n",maker,i);
i=va_arg(maker,int);
}
}
void main(void)
{
average(2,3,4,4,-1);
}
运行结果:
FFCE: 2
FFD0: 3
FFD2: 4
FFD4: 4
这个程序显示函数参数的地址相差2个字节
所以可以改写为:
void x(char *n,...)
{int *p;
p=n;
while(*p!=-1)
{printf("%p:%s\n",p,*p,*p);
p+=sizeof(char);}}
void main()
{x("g","hfd","gfg","vsds",-1);}
运行结果:
FFD2:g
FFD4:hfd
FFD6:gfg
FFD8:vsds
不必通过宏va_start,va_arg,va_end实现
C语言中定义了va_list, va_start( ), va_arg( ), va_end( ) 这样一组宏来处理可变参数问题。
可以参考printf的声明,创建自己的实现函数。示例:
#includestdio.h
#includestdarg.h
void va_fun(int start,...)
{
va_list arg_ptr;
int nArgValue = start;
int nArgCount = 1;
va_start(arg_ptr,start);
while(nArgValue != -1)
{
printf("arg %d is:%d/n",nArgCount,nArgValue);
nArgValue=va_arg(arg_ptr,int);
++nArgCount;
}
return;
}
main()
{
va_fun(5,1,7,-1);
printf("................/n");
va_fun(2,4,-1);
printf("................/n");
va_fun(-1);
printf("................/n");
//va_fun(); 可变参数函数最少要有一个参数。
}
很巧我现在正好也有实现这样函数的需求,其实就是看了C语言可变参数函数的相关资料,你就差不多知道怎么实现了。
只不过其中有一个很重要的大坑,只要迈过去就没问题。我是试了半天才明白的:
如果参数是char或float类型,这样的参数放在可变参数部分的话,编译器是会默认把它们的类型提升为相应的“全”类型的:char提升为int,float提升为double。如果你没注意这一点就会出现错误。当然可以通过指针的类型转换来避免。
先简略地点一下,等我在CSDN博客里详细地写一写心得吧。虽然是N年前的问题估计楼主早就自己解决了,但希望能帮到其他人:)
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流