首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

可变参数的一些议论

2013-10-16 
可变参数的一些讨论现象:函数A定义了一个双指针的固定参数然后是可变参数: int A( void **pHandle,...)A

可变参数的一些讨论
现象:
函数A定义了一个双指针的固定参数然后是可变参数: int A( void **pHandle,...);
A函数在一个动态链接库中被实现。
调用的时候,第一次在main函数中直接调用这个函数,且固定参数为一个全局变量,设计中的几种参数组合都可以正常调用。
第二次调用的时候只是将第一次的main函数名字改掉并重新写一个main函数来调用该函数,但是发现在进入到A函数后,存储参数地址列表的内存中,跟在有效参数地址后面的值不再是0,从而导致获取参数时无法正常获取。

不知道文字描述是不是清楚,简单用代码描述下。


/*
* A.h
*/
...
DLL int A( void **pHandle,... );
...


/*
* 调用正常
*/
...
void *handle = NULL;

void main()
{
int rv = 0;

{
rv = A(&handle);/*这种方式在函数A中跟踪到内存(&pHandle+4)的地方值是0*/
...
}

{
rv = A(&handle,"config.ini");
...
}

{
rv = A(&handle,"127.0.0.1",8000);
...
}

return;
}


/*
* 调用异常
*/
...
void *handle = NULL;

void initdll()
{
int rv = 0;

{
rv = A(&handle);/*这种方式在函数A中跟踪到内存(&pHandle+4)的地方值是一个非0值,且该值所指向的地址也有值。*/
...
}

{
rv = A(&handle,"config.ini");
...
}

{
rv = A(&handle,"127.0.0.1",8000);
...
}

return;
}

void main()
{
initdll();
return;
}


想不明白这两种不同的调用方式为什么会出现参数地址的不同。
可变参数 指针 异常 内存 c
[解决办法]
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

[解决办法]
引用:
唉,好像不能这么用啊,参数里至少需要有能够标识变参个数的地方才行。

就是这么用的可以这么用问题是你函数里面怎么处理的,随便从内核中拉了个例子出来

static void ad1843_read_multi(struct snd_ad1843 *ad1843, int argcount, ...)
{
va_list ap;
const struct ad1843_bitfield *fp;
int w = 0, mask, *value, reg = -1;

va_start(ap, argcount);
while (--argcount >= 0) {
fp = va_arg(ap, const struct ad1843_bitfield *);
value = va_arg(ap, int *);
if (reg == -1) {
reg = fp->reg;
w = ad1843->read(ad1843->chip, reg);
}

mask = (1 << fp->nbits) - 1;
*value = w >> fp->lo_bit & mask;
}
va_end(ap);
}


void va_start( va_list arg_ptr, prev_param ); 
用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数. 
 type va_arg( va_list arg_ptr, type ); 
用va_arg返回可变的参数,并返回. va_arg的第二个参数是你要返回的参数的类型,这里是int型.
 然后你就可以在函数里使用第二个参数了.如果函数有多个可变参数的,依次调用va_arg获取各个参数.
  void va_end( va_list arg_ptr );
va_end宏结束可变参数的获取.
[解决办法]
/* * 调用正常 */... void *handle = NULL;   void main() {     int rv = 0;       {         rv = A(&handle);/*这种方式在函数A中跟踪到内存(&pHandle+4)的地方值是
//说明不了问题,那是个随机值,可变参数函数,你的函数必须能清楚解释传入的数据类型,参数结束

//可以像printf 第一个参数是格式串,该串可以用于对每个后续参数进行解释,直到最后一个
//或者传递,相同类型的参数,你可以使用第一个参数指明参数个数,或者最后一个参数使用特殊值指明参数表结束
//或者使用变体变量,最后一个参数设置为NULL
0*/        ...     }       {         rv = A(&handle,"config.ini");         ...     }       {         rv = A(&handle,"127.0.0.1",8000);         ...     }       return; } 

热点排行