可变参数的理解

c中的printf中的参数就是典型的可变参数,参数不固定,那怎么获取呢

正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈

#include <stdio.h>
#include <stdlib.h>

#define __va_rounded_size(TYPE)  \
  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

void test(int a, int b){
        printf("a address is %x\n", &a);
        printf("b address is %x\n", &b);

        char* addr = (char*)&b ;
        printf("b values is %d\n", *(int*)addr);

        addr = addr + sizeof(int);  //这里如果是long, 那么a的值是0,但没报错
        printf("a values is %d\n", *(int*)addr);
}

int main(){
        test(1,2);
        return 0;
}

结果为

a address is 3e20571c
b address is 3e205718
b values is 2
a values is 1

明显b的地址要高于a, b先于a入栈

肯定知道b的地址,那么a的值 就是 *(int) (&b+sizeof(int))

参考这里

时间: 2024-10-27 05:59:16

可变参数的理解的相关文章

c语言中对可变参数列表的简单理解

函数原型中一般情况下参数的数目是固定的,但是如果想在不同的时候接收不定数目的参数时该怎么办呢?c语言提供了可变参数列表来实现. 可变参数列表是通过宏来实现的,这些宏定义在stdarg.h的头文件中.头文件中声明了一个va_list类型和va_start.va_arg.va_end三个宏.我们使用可变参数列表的时候需要声明一个va_list类型的变量配合这三个宏使用. va_start(va_list变量名,省略号前面最后一个有名字的参数):在提取可变参数前必须调用这个宏实现初始化. va_arg

理解 Python 中的可变参数 *args 和 **kwargs:

默认参数:  Python是支持可变参数的,最简单的方法莫过于使用默认参数,例如: def getSum(x,y=5): print "x:", x print "y:", y print "x+y :", x + y getSum(1) # result: # x: 1 # y: 5 # x+y : 6 getSum(1,7) # result: # x: 1 # y: 7 # x+y : 8 可变参数: 另外一种达到可变参数 (Variabl

C语言的可变参数

可变参数给编程带来了很大的方便,在享受它带来的方便的同时,很有必要了解一下其实现方式,在了解编程语言的同时,也可以扩展编程的思路. 可变参数需要用到3个宏函数和一个类型,他们都定义在<stdarg.h>中,分别是: va_start(vl) va_arg(vl, type) va_end(vl) 其中vl是va_list类型,type就是对象类型(如int, double或 自定义的struct之类的). va_start函数用来初始化vl va_arg(vl, type)用来取得type类型

Java 可变参数

可变参数 可变参数可以当成一个数组使用 public void sum(int ...nums){ int sum = 0; for(int i:nums) { sum +=i; } System.out.println(sum); } @Test public void testSum() { sum(1,2,3,4,5); } 可变参数的实参可以是数组(同上) @Test public void testSum() { int arr[] ={1,2,3,4,5}; sum(arr); }

C语言可变参数函数实现原理

一.可变参数函数实现原理 C函数调用的栈结构: 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 本文地址:http://www.cnblogs.com/archimedes/p/variable-parameter.html,转载请注明源地址. 例如,对于函数: void fun(int a, int b, int c) { int d; ... } 其栈结构为 0x1ffc-->d 0x200

C++ 11可变参数接口设计在模板编程中应用的一点点总结

概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量(或属性,C#中属性和成员变量还是有区别的): 类的成员方法: 从编译器的角度看,我们必须明确指定以上3部分,才算完整地定义了一个类并且编译通过. 所谓的“类弱化”,是指类的设计者在定义类的时候,并没有完整定义一个类,而是把类的其中一部分的定义留给类的使用者. 从传统才c++98看,通过模板类,使用

C++11新特性之五——可变参数模板

有些时候,我们定义一个函数,可能这个函数需要支持可变长参数,也就是说调用者可以传入任意个数的参数.比如C函数printf(). 我们可以这么调用. printf("name: %s, number: %d", "Obama", 1); 那么这个函数是怎么实现的呢?其实C语言支持可变长参数的. 我们举个例子, double Sum(int count, ...) { va_list ap; double sum = 0; va_start(ap, count); fo

C语言利用va_list、va_start、va_end、va_arg宏定义可变参数的函数

在定义可变参数的函数之前,先来理解一下函数参数的传递原理: 1.函数参数是以栈这种数据结构来存取的,在函数参数列表中,从右至左依次入栈. 2.参数的内存存放格式:参数的内存地址存放在内存的堆栈段中,在执行函数的时候,从最后一个(最右边)参数开始入栈.因此栈底高地址,栈顶低地址,举个例子说明一下: void test(int a, float b, char c); 那么,在调用test函数的时候,实参char c先进栈,然后是float b,最后才是int a,因此在内存中变量的存放次序是c->

C/C++函数中使用可变参数

先说明可变参数是什么,先回顾一下C++里面的函数重载,如果重复给出如下声明: 1 int func(); 2 int func(int); 3 int func(float); 4 int func(int, int); 5 ... 这样在调用相同的函数名 func 的时候,编译器会自动识别入参列表的格式,从而调用相对应的函数体. 但这样的方法毕竟有限,试想一下我们假如想定义一个函数,我们在调用之前(在运行期之前)根本不知道我到底要调用几个参数,并且不知道这些参数是个什么类型,例如我们想定义一个