b2c信息网

您现在的位置是:首页 > 热点事件 > 正文

热点事件

可变参数列表源码的剖析(可变参数调用可变参数)

hacker2022-06-08 10:55:21热点事件95
本文目录一览:1、

本文目录一览:

关于C++可变参数的问题,请达人看下面代码,为什么24.0,如果没有后面的.0,会出现数据异常或者溢出呢?

我们按照32位系统来讲。

首先需要知道一些编译器的默认类型问题,整数常量默认为int(4字节),浮点数常量默认为double类型(8字节)。

其次,来看这一句:sum+=va_arg(ap,double);

你在这里指定了参数是double类型,va_arg的作用是从地址ap开始返回一个double类型的数,并且ap地址向后移动double类型所占的字节数,这一句分解下可以看成这样:

sum = sum + *(double *)ap;

ap = ap +8;

而如果参数里不加小数点的话,默认是int类型,在这里ap的地址加8的话直接就错位了,所以会混乱。

所以解决的办法就是,要么加小数点,要么显示指明数字常量位double类型,如:double iA=add(3,24.0,42.6,56.8);这句改成:

double iA=add(3,(double)24,(double)426,(double)568);

c语言中什么是可变参数?最好有简单的应用可变参数的例子。谢谢

一个简单的可变参数的函数的例子:

#include stdio.h

#include stdarg.h

void Func(int count, ...) //可变形参的函数的定义

{

va_list ap;

int n = count; //使用count来表示后面的参数个数

char *s = NULL;

int d = 0;

double f = 0.0;

va_start(ap, count); // 从第二个形参开始读取

s = va_arg(ap, char*); //为形参指定类型char*

d = va_arg(ap, int); //为形参指定类型int

f = va_arg(ap, double); //为形参指定类型double

va_end(ap); //读取形参结束

printf( "%s %d %f ", s, d, f); //这里可以做想要的功能了。

}

main()

{

Func(3, "Hello", 345, 788.234);

}

c++ 变长参数列表

在C编译器通常提供了一系列处理可变参数的宏,实现就像printf()那样的变长参数列表,这样可以屏蔽不同的硬件平台造成的差异,增加程序的可移植性。这些宏包括va_start、 va_arg和va_end等,这些宏都是在头文件stdarg.h里定义的。

采用ANSI标准形式时,参数个数可变的函数的原型声明是:

type funcname(type para1, type para2, ...)

这种形式至少需要一个普通的形式参数,后面的省略号不表示省略,而是函数原型的一部分。type是函数返回值和形式参数的类型。

不同的编译器,对这个可变长参数的实现不一样 ,gcc4.x中是采用内置函数的方法来实现。

接下来我们看看以下示例代码:

#include stdarg.h

#include stdio.h

int Sum (int n, ...)

{

int sum = 0, i = 0;

va_list p; // 定义一个变量 ,保存函数参数列表的指针。

va_start(p, n); // 用va_start宏初始化变量p,

// va_start宏的第2个参数n,

// 是一个固定的参数,

// 必须是我们自己定义的变长函数的最后一个入栈的参数,

// 也就是调用的时候参数列表里的第1个参数。

for (i = 1; i n; ++ i) // i从1开始,遍历所有可变参数。

{

sum += va_arg(p, int); // va_arg取出当前的参数,

// 并认为取出的参数是一个整数(int) 。

}

return sum;

}

int main(void)

{

int num;

num = Sum(5, 1, 2, 3, 4);

printf("%d\n", num);

return 0;

}

当我们调用Sum函数时,传递给Sum函数的参数列表的第一个参数n的值是5,va_start 初始化p使其指向第一个未命名的参数(n是有名字的参数) ,也就是1(第一个),每次对 va_arg的调用,都将返回一个参数,并且把 p 指向下一个参数,va_arg 用一个类型名来决定返回的参数是何种类型,以及在 var_arg的内部实现中决定移动多大的距离才到达下一个参数。

C语言中可变参数宏的va_start(ap, v)

我把你的提问分为3个问题:

1、为什么printf("%s", ap);输出不了?

2、va_start(ap, v)的定义中为什么使用二级指针?

3、va_arg(ap,t) 的定义中为什么用*(t *),它的作用是?

在解释之前,先确认一个小问题:

在C语言中,指针这种类型的大小实际上一样的,我的意思是说无论是char *a,还是int *a,或者是char **a,a这个指针变量所占用的内存空间是一样的(都是sizeof(a),究竟是等于4,还是8取决于CPU的位数)

先回答第一个问题:

你应该知道va_list的定义:typedef char * va_list;

也就是说ap可以理解为一个char *类型的变量,va_start(ap,c)这个执行之后,ap确实指向了可变参数列表中的第一个参数,注意【是ap这个指针指向了第一个参数】,而如果你的第一个参数是一个字符串(C语言中也就意味着是一个char*的变量),这样的话,ap这个指针就指向了一个char*类型的指针变量,【指向指针的指针变量是二级指针变量】这个我就不用多说了吧,所以printf("%s", ap);是无法输出的,而修改为printf("%s", *(char **)ap);应该就可以输出了!

然后是第二个问题:

这里先说一下函数调用过程中参数传递的问题:

【 函数参数是以数据结构:栈的形式存取,从右至左入栈。

首先是参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址,举个例子如下:

void func(int x, char *y, char z);

那么,调用函数的时候,实参 char z 先进栈,然后是 char *y,最后是 int x,因此在内存中变量的存放次序是 x-y-z,因此,从理论上说,我们只要探测到任意一个变量的地址,并且知道其他变量的类型,通过指针移位运算,则总可以顺藤摸瓜找到其他的输入变量。】

注意,x,y,z这几个变量是存放到堆栈中的,所以我们需要获得的不是y这个变量本身,而是它在堆栈中的地址,而ap这个指针变量就是保存着堆栈中函数入参的地址的,所以在va_start(ap, v)的定义中要使用v,而不管v变量本身是什么类型的(哪怕v是一个指针变量,甚至是二级指针)v都表示一个地址,所以可以强制转换为va_list类型(也就是char *)。

第三个问题:

要睡觉了,先自己想吧,如果还不明白,就留言追问吧。

简单谈谈Python中函数的可变参数

简单谈谈Python中函数的可变参数

在Python中定义函数,可以用必选参数、默认参数、可变参数和关键字参数,这4种参数都可以一起使用,或者只用其中某些,但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数。

可变参数( * )

可变参数,顾名思义,它的参数是可变的,比如列表、字典等。如果我们需要函数处理可变数量参数的时候,就可以使用可变参数。

我们在查看很多Python源码时,经常会看到 某函数(*参数1, **参数2)这样的函数定义,这个*参数和**参数就是可变参数,一时会让人有点费解。其实只要把函数可变参数的定义搞清楚了,就不难理解了。

当我们不知道需要用几个参数来定义函数的时候,可变参数就可以大展手脚了。

在Python里,带 * 的参数就是用来接受可变数量参数的。

如果一个函数定义如下:

def functionTest(*args):

....

....

....

调用时我们可以的这样调用:

functionTest(1)

或者

functionTest(1,2)

或者

functionTest(1,2,3)

后面可以传入多个参数。

看段实例代码,观察下*是怎么具体应用的吧:

def get_sum(*numbers):

sum = 0

for n in numbers:

sum += n

return sum

#在这里写下你的代码来调用get_sum来求5个数字的和,并输出这个结果

print (get_sum(1,2,3,4,5))

结果会是什么呢?大家可以自己动手操作起来看下,以就是关于Python中函数可变参数的全部内容,希望这篇文章对大家学习或使用python能有所帮助

发表评论

评论列表

  • 断渊瑰颈(2022-06-08 18:35:27)回复取消回复

    (double)426,(double)568);c语言中什么是可变参数?最好有简单的应用可变参数的例子。谢谢一个简单的可变参数的函数的例子:#include stdio.h#include stdarg.hvoid Func(int

  • 忿咬掩吻(2022-06-08 11:54:16)回复取消回复

    都表示一个地址,所以可以强制转换为va_list类型(也就是char *)。第三个问题:要睡觉了,先自己想吧,如果还不明白,就留言追问吧。简单谈谈Python中函数的可变参数简单谈谈Python中函

  • 双笙云棉(2022-06-08 18:07:08)回复取消回复

    rt(ap, v)5、简单谈谈Python中函数的可变参数关于C++可变参数的问题,请达人看下面代码,为什么24.0,如果没有后面的.0,会出现数据异常或者溢出呢?我们按照32位系统来讲。首先需要知道一些编译器的默认类型问题,整数常量默认为int(

  • 只影折木(2022-06-08 22:29:17)回复取消回复

    iA=add(3,(double)24,(double)426,(double)568);c语言中什么是可变参数?最好有简单的应用可变参数的例子。谢谢一个简单的可变参数的函数的例子:#include stdio.h#include stdarg.hvoid Func(int co

  • 绿邪寻倌(2022-06-08 22:11:46)回复取消回复

    形式参数,后面的省略号不表示省略,而是函数原型的一部分。type是函数返回值和形式参数的类型。 不同的编译器,对这个可变长参数的实现不一样 ,gcc4.x中是采用内置函数的方法来实现。接下来我们看看以下示例代码:#include stdarg.h#include