C语言函数的变参实用与分析

实现变参传递的关键是:

传入参数在内存中是连续分布的。

#define va_list void*
#define va_arg(arg, type)     *(type*)arg; arg = (char*)arg + sizeof(type);
#define va_start(arg, start)  arg = (va_list)(((char*)&(start)) + sizeof(start))
#define va_end(arg)  arg = (void*)0

这四个宏其实是c语言定义好的在stdarg.h中。通过va_start(arg, start)传入第一个参数以确定后面参数的地址。 va_arg(arg, type)取出arg的值,并将地址指向下一个
#include <stdio.h>

#define va_list void*
#define va_arg(arg, type)     *(type*)arg; arg = (char*)arg + sizeof(type);
#define va_start(arg, start)  arg = (va_list)(((char*)&(start)) + sizeof(start))
#define va_end(arg)  arg = (void*)0
int sum(int nr, ...)
{
    int i = 0;
    int result = 0;
    va_list arg = NULL;///不定类型指针
    va_start(arg, nr);//让指针指向第二个参数地址

    for(i = 0; i < nr; i++)
    {
        result += va_arg(arg, int);
    }
    va_end(arg);
    return result;
}

int main(int argc, char* argv[])
{
    printf("%d\n", sum(4, 100,100,100,100));
    printf("%d\n", sum(3, 200, 200, 200));

    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
 /*

 #define va_list void*
#define va_arg(arg, type)     *(type*)arg; arg = (char*)arg + sizeof(type);
#define va_start(arg, start)  arg = (va_list)(((char*)&(start)) + sizeof(start))

这些在stdarg.h中定义过
 */
void printf_diy(char *fmt,...) {
        va_list arg;  //定义一个不定类型指针
        char c;  

        va_start(arg, fmt);  //arg指向下一个参数

        do {
                c = *fmt;
                if(c != ‘%‘){
                        putchar(c); //输出
                }
                else {
                        fmt++;
                        switch(*fmt) {
                        case ‘d‘:
                                printf("%d", *((int*)arg));
                                break;
                        case ‘x‘:
                                printf("%#x", *((int*)arg));
                                break;
                        case ‘f‘:
                                printf("%f", *((float*)arg));
                        default:
                                break;
                        }  

                        va_arg(arg,int);
                }  

                ++fmt;  

        } while (*fmt != ‘\0‘);  

        va_end(arg);
        return;
}  

int main(int argc, char **argv) {
        int i = 1234;
        int j = 5678;
        float f = 13.9;  

        printf_diy("i = %d\n", i);
        printf_diy("j = %d\n", j);
        printf_diy("f = %f\n", f);
        return 0;
}  
时间: 2024-10-09 17:57:51

C语言函数的变参实用与分析的相关文章

R语言学习-对象处理实用函数

R语言的对象处理实用函数可视为一个分析变量(或对象)的工具集,类似于Java中的反射功能,但使用起来更简单. 处理数据对象的实用函数见下表: 函数 用途 length(object) 显示对象中元素/成分的数量 dim(object) 显示某个对象的维度 str(object) 显示某个对象的结构 class(object) 显示某个对象的类或类型 mode(object) 显示某个对象的模式 names(object) 显示某对象中各成分的名称 c(object, object,-) 将对象合

C语言之可变参实现scanf函数

既然有printf函数可变参实现,那就一定有scanf函数的可变参实现.废话不多说,源码奉上: 本源码不过多分析,如要明白原理,请翻本博客以往的文章看说明. 欢迎关注新浪微博:http://weibo.com/u/1896293701/home?topnav=1&wvr=6 #include <stdio.h> #include <stdarg.h> int myscanf(const char *fmt , ...) ; int main(void) { int num

(转)如何编写有多个返回值的C语言函数

1引言    笔者从事C语言教学多年,在教学中学生们常常会问到如何编写具有多个返回值的C语言函数.编写有多个返回值的函数是所有C语言教材里均没有提到的知识点,但在实际教学与应用的过程中我们都有可能会遇到这样的问题.有学生也尝试了不少方法:如把多个需要返回的值作相应的处理后变成一个可以用return语句返回的数据,再在主调函数中拆开返回的数据使之变成几个值:或者把需要返回多个值的一个函数分开几个函数去实现多个值的返回.这些方法虽然最终都能实现返回要求的多个值,但从程序算法的合理性与最优化方面去考虑

汇编1 ----C语言函数1

构造以下C程序并在合适位置插入breakpoints 在Visual Studio 2015 CTP6对其反汇编. 下面来分析 z = add(1, 2); 009C170E 6A 02 push 2 ????int z; ????z = add(1, 2); 009C1710 6A 01 push 1 009C1712 E8 8D FA FF FF call 009C11A4 009C1717 83 C4 08 add esp,8 009C171A 89 45 F8 mov dword ptr

从linux0.11中起动部分代码看汇编调用c语言函数

上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一段代码(linux0.11的启动分析部分会在另一部分中再分析,由于此文仅涉及c与汇编代码的问题,). after_page_tables: pushl $0 # These are the parameters to main :-) pushl $0 pushl $0 pushl $L6 # re

linux下C语言函数执行时间统计

转载:http://blog.csdn.net/linquidx/article/details/5916701#t5 写好程序,用gcc编译,带上-pg参数,然后运行以后分析gmon.out文件: 命令exp:   gprof ./test-main ./gmon.out >1.log  在1.log中会生成各函数运行情况. gprof 1.1 简介 gprof实际上只是一个用于读取profile结果文件的工具.gprof采用混合方法来收集程序的统计信息,他使用检测方法,在编译过程中在函数入口

c语言函数的秘密

一:自创函数 C语言提供了大量的库函数(右侧资料下载中有),比如stdio.h提供输出函数,但是还是满足不了我们开发中的一些逻辑,所以这个时候需要自己定义函数,自定义函数的一般形式: 注意: 1.[]包含的内容可以省略,数据类型说明省略,默认是int类型函数:参数省略表示该函数是无参函数,参数不省略表示该函数是有参函数: 2.函数名称遵循标识符命名规范: 3.自定义函数尽量放在main函数之前,如果要放在main函数后面的话,需要在main函数之前先声明自定义函数,声明格式为:[数据类型说明]

C语言 03-第一个C程序代码分析

本文目录 一.代码分析 二.开发和运行C程序的步骤 三.总结 说明:这个C语言专题,是学习iOS开发的前奏.也为了让有面向对象语言开发经验的程序员,能够快速上手C语言.如果你还没有编程经验,或者对C语言.iOS开发不感兴趣,请忽略. 在上一篇中我们已经创建了一个C程序,接下来分析一下里面的代码. 项目结构如下: 一.代码分析 打开项目中的main.c文件(C程序的源文件拓展名为.c),可以发现它是第一个C程序中的唯一一个源文件,代码如下: 1 #include <stdio.h> 2 3 in

05. Go 语言函数

Go 语言函数 函数是组织好的.可重复使用的.用来实现单一或相关联功能的代码段,其可以提高应用的模块性和代码的重复利用率. Go 语言支持普通函数.匿名函数和闭包,从设计上对函数进行了优化和改进,让函数使用起来更加方便. Go 语言的函数属于"一等公民"(first-class),也就是说: 函数本身可以作为值进行传递. 支持匿名函数和闭包(closure). 函数可以满足接口. Go语言函数声明(函数定义) 函数构成了代码执行的逻辑结构,在Go语言中,函数的基本组成为:关键字 fun