本文主要介绍va_start和va_end的使用及原理。
在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end这两个宏,但对它们也只是泛泛的了解。
介绍这两个宏之前先看一下C中传递函数的参数时的用法和原理:
void foo(...);
void foo(parm_list,...);
这种方式和我们以前认识的不大一样,但我们要记住这是C中一种传参的形式,在后面我们就会用到它。
函数参数是以数据结构:栈的形式存取,从右至左入栈。
首先是参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址,举个例子如下:
void func(int x, float y, char z);
那么,调用函数的时候,实参 char z 先进栈,然后是 float y,最后是 int x,因此在内存中变量的存放次序是 x->y->z,因此,从理论上说,我们只要探测到任意一个变量的地址,并且知道其他变量的类型,通过指针移位运算,则总可以顺藤摸瓜找到其他的输入变量。
下面是 <stdarg.h> 里面重要的几个宏定义如下:
typedef char* va_list;
void va_start ( va_list ap, prev_param ); /* ANSI version */
type va_arg ( va_list ap, type );
void va_end ( va_list ap );
va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。
<Step 1> 在调用参数表之前,定义一个 va_list 类型的变量,(假设va_list 类型变量被定义为ap);
<Step 2> 然后应该对ap 进行初始化,让它指向可变参数表里面的第一个参数,这是通过 va_start 来实现的,第一个参数是 ap 本身,第二个参数是在变参表前面紧挨着的一个变量,即“...”之前的那个参数;
<Step 3> 然后是获取参数,调用va_arg,它的第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回这个指定类型的值,并且把 ap 的位置指向变参表的下一个变量位置;
<Step 4> 获取所有的参数之后,我们有必要将这个 ap 指针关掉,以免发生危险,方法是调用 va_end,他是输入的参数 ap 置为 NULL,应该养成获取完参数表之后关闭指针的习惯。说白了,就是让我们的程序具有健壮性。通常va_start和va_end是成对出现。 例如 int max(int n, ...); 其函数内部应该如此实现:
#include <iostream.h>
void fun(int a, ...)
{
int *temp = &a;
temp++; //评论中反馈有问题,待改中
for (int i = 0; i < a; ++i)
{
cout << *temp << endl;
temp++;
}
}
int main()
{
int a = 1;
int b = 2;
int c = 3;
int d = 4;
fun(4, a, b, c, d);
system("pause");
return 0;
}
Output::
1
2
3
4
在函数体中声明一个va_list,然后用va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束。像这段代码:
void TestFun(char* pszDest, int DestLen, const char* pszFormat, ...)
{
va_list args;
va_start(args, pszFormat); //一定要“...”之前的那个参数
_vsnprintf(pszDest, DestLen, pszFormat, args);
va_end(args);
}
#include 〈stdio.h〉
#include 〈string.h〉
#include 〈stdarg.h〉
/*函数原型声明,至少需要一个确定的参数,注意括号内的省略号*/
int demo( char, ... );
void main( void )
{
demo("DEMO", "This", "is", "a", "demo!", "");
}
/*ANSI标准形式的声明方式,括号内的省略号表示可选参数*/
int demo( char msg, ... )
{
/*定义保存函数参数的结构*/
va_list argp;
int argno = 0;
char para;
/*argp指向传入的第一个可选参数,msg是最后一个确定的参数*/
va_start( argp, msg );
while (1)
{
para = va_arg( argp, char);
if ( strcmp( para, "") == 0 )
break;
printf("Parameter #%d is: %s\n", argno, para);
argno++;
}
va_end( argp );
/*将argp置为NULL*/
return 0;
}
新的ubuntu24.04正式版发布了,前段时间玩了下桌面版,感觉还行,先安装一个服务器无界面版本吧安装时有一个openssh选择安装,要不然就不能ssh远程,我就是没选,后来重新安装ssh。另外一个就是安装过程中静态ip设置下在etc/netplan 文件夹下,有一个yaml文件,我的是50-cloud-init.yaml,先用ip a看看network:ethernets:enp3s0:routes:version: 2。
文章浏览阅读176次。写在前面MySQL被设计为一个可移植的数据库,几乎在当前所有系统上都能运行,如Linux、Solaris、 FreeBSD、 Mac和Windows。尽管各平台在底层(如线程)实现方面都各有不同,但是MySQL基本上能保证在各平台上的物理体系结构的一致性。因此,用户应该能很好地理解MySQL数据库在所有这些平台上是如何运作的。由于工作的缘故,笔者的大部分时间需要与开发人员进行数据库方面的沟通,并对他们进行培训。不论他们是DBA,还是开发人员,似乎都对MySQL的体系结构了解得不够透彻。很多人喜欢把M_mysql运维内参
文章浏览阅读382次。晓查 发自 凹非寺量子位 报道 | 公众号 QbitAI9102年,人类依然不断回想起围棋技艺被AlphaGo所碾压的恐怖。却也有不以为然的声音:只会下棋的AI,再厉害..._alpha go训练用了多少个gpu
文章浏览阅读3.3k次。docker 容器 设置网络代理以/bin/bash 形式进入容器:【设置http 及https代理】,如下:export http_proxy=http://172.16.0.20:3128export https_proxy=https://172.16.0.20:3128要取消该设置:unsethttp_proxyunset https_proxy..._docker export http_proxy
文章浏览阅读263次。授课环境: 结束程序运行: ctrl + c 共享目录(工作目录): /kyo /Videos 访问共享目录流程: 是否能连通服务器 ping 3.3.3.9 是否服务器开启共享 showmount -e 3.3.3.9 挂载共享目录到本地: _linux 0775十六進制
与普通屏幕中播放的视频相对,裸眼3D屏幕需要先将裸眼3D视频分成两部分,分别呈现在左右两个视窗上,因此后者需要更高的分辨率,以及更精细的图像处理能力,以此使裸眼3D屏幕的画面展示效果更加细腻,进而加深每个物体和场景的深度感和空间感,让每个驻足于此的观众惊叹于裸眼3D屏幕的震撼视觉效果。另外,裸眼3D屏幕的色彩表现,也比大多的普通屏幕更加丰富和鲜艳,能够展现出电影级别的画面质量,总而言之,裸眼3D屏幕比之普通屏幕的显示效果,有着巨大的优势,这也是使裸眼3D成为重要显示技术的重要原因!
文章浏览阅读5.1k次,点赞2次,收藏70次。K210与STM32之间使用串口进行通信_k210与stm32通信
而网上有关鸿蒙的开发资料非常的少,假如你想学好鸿蒙的应用开发与系统底层开发。你可以参考这份资料,少走很多弯路,节省没必要的麻烦。由两位前阿里高级研发工程师联合打造的《鸿蒙NEXT星河版OpenHarmony开发文档》里面内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点。
2、本次测试了两款IDE,分别是"thonny-4.1.4.exe"和"uPyCraft-v1.0.exe"。Thonny支持中文及多语言。而uPyCraft-v1.0只支持英文语言。因此入门时选用了Thonny作为IDE。(注:1、测试过程中IDE正常连接ESP32C3简约版的虚拟串口。不受简约版无串口芯片的影响。
古有匈奴犯汉,晋室不纲,铁木夺宋,虏清入关,神舟陆沉二百年有余,中国之见灭于满清初非满人能灭之,能有之也因有汉奸以作虎怅,残同胞媚异种,始有吴三桂洪承畴,继有曾国藩袁世凯以为厉。今率堂堂之师,征讨汉贼袁氏筑共和之体,或免于我子子孙孙被异族奴役。---- 《讨汉贼袁世凯檄文》- DOMContentLoaded事件:此时浏览器已经完全加载了HTML文件,并且DOM树已经生成好了。- Load事件:此时浏览器已经将所有的资源都加载完毕,可以正确读取页面中的资源。补充知识:Electron 生命周期。
将ENABLE_USER_SCRIPT_SANDBOXING设为“no”即可!
文章浏览阅读2.8k次,点赞3次,收藏23次。一、实现路径通过OpenVINO部署YOLO模型到边缘计算摄像头,其实现路径为:训练(YOLO)->转换(OpenVINO)->部署运行(OpenNCC)。二、具体步骤1、训练YOLO模型1.1 安装环境依赖有关安装详情请参阅 https://github.com/AlexeyAB/darknet#requirements-for-windows-linux-and-macos 。1.2 编译训练工具git clone https://github.com/AlexeyAB/da_openvino yolo