发布时间:2022-08-09 文章分类:编程知识 投稿人:王小丽 字号: 默认 | | 超大 打印

C语言可变参数,参数传递

1、函数形参的存储

函数形参在函数中存储是按照栈的方式来存储的

实例:

复制代码
#include <stdio.h>
void fun(int a0,int a1,int a2, int a3)
{
    int *temp;
    temp=&a0;
    int i;
    for(i=0;i<4;i++){
        printf("%d\t",*temp++);
    }
}
int main(){
    fun(1,2,3,4);
    getchar();
    return 0;
}
复制代码

函数输出为:

1  2  3  4

2、一般函数的定义在内存中的存储方式

一般的变量定义之后,相同的变量类型存储在相邻的一块内存

例子:

复制代码
#include <stdio.h>
int main()
{
    int a0=1;
    char c0='a';
    double d0=1.1;
    char c1='b';
    double d1=2.2;
    int a1=2;
  int a2=3;
    int *pint = &a0;
    char *pch = &c0;
    double *pd = &d0;

    printf("%p:%d\n", pint, *pint);
    pint++;
    printf("%p:%d\n", pint, *pint);
    pint++;
    printf("%p:%d\t%p\n", pint, *pint);
    printf("%p:%c\n", pch, *pch);
    pch++;
    printf("%p:%c\n", pch, *pch);
    printf("%p:%.2f\n", pd, *pd);
    pd++;
    printf("%p:%.2f\n", pd, *pd);
}
复制代码

输出:

0xbf944c54:1
0xbf944c58:2
0xbf944c5c:3
0xbf944c6e:a
0xbf944c6f:b
0xbf944c40:1.10
0xbf944c48:2.20

**这个结论只是对于我自己的编译器的结果,具体可能对于另外一个编译器的输出有有可能不一样,而且,如果把有变量没有使用过的话,编译器有可能丢弃它(自己的猜想而已,等过阵子研究《深入理解计算机系统》的时候在研究这个问题)。

3、C语言给我们的可变形参va_list

头文件stdarg.h

下面定义了四个宏:

1. va_list

在stdarg.h中定义:typedef char * va_list;

2. void va_start(va_list ap,last);

这是第一个调用的宏,last是可变参数的前一个确定的参数。因此只有可变参数的函数是不允许的,如fun(...)是不合法的。

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址

3. void va_arg(va_list ap, type);

返回当前参数并且使ap指向下一个参数,type是明确的类型名,就是获取的类型,不是。

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址

4. void va_end(va_list ap);

有va_start就必须有va_end,作用是使释放ap

#define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效

4. void va_copy(va_list dest, va_list src);

每次调用va_copy时也必须要有va_end调用。

例子:

复制代码
#include <stdio.h>
#include <stdarg.h>
void fun(int a,...){
    va_list ap;
    va_start(ap, a);
    int i;
    for(i=0; i<a; i++){
        printf("%d\t",va_arg(ap,int));
    }
    putchar('\n');
    va_end(ap);
}
int main(){
    fun(4,1,2,3,4);
    printf("--------------------------------\n");
    fun(4,1,2,"ab","cd");
    return 0;
}
复制代码

输出:

1 2 3 4
--------------------------------
1 2 134514184 134514181