zoukankan      html  css  js  c++  java
  • C语言println函数

    发现很多现代的语言中都有println这个函数,用起来很是方便,不用每次打印都要加上" ",自己也实现了一个,方便平时调试的时候用。

    1. #include <stdarg.h>
    2. int println(const char *fmt, ...)
    3. {
    4. char printf_buf[1024];
    5. va_list args;
    6. int printed;
    7. va_start(args, fmt);
    8. printed = vsprintf(printf_buf, fmt, args);
    9. va_end(args);
    10. puts(printf_buf);
    11. return printed;
    12. }

    这里用到了C语言的可变参函数,就顺便谈谈C语言的可变参函数吧。所谓可变参函数即函数的参数可以是不定个数。上面我们已经看到了变参函数的定义方法,用形如int println(const char *fmt, ...)来定义可变参函数。

    注意:上例中的第一个参数fmt是不可省略的,可变参函数至少需要一个普通的形参。


    C语言之所以支持可变参函数,一个重要的原因是C调用规范中规定了C语言函数调用时,参数入栈的书序是从右往左,这意味着,栈顶的参数是第一个参数。这样,被调用的函数,就不需要关心调用者会传递几个参数进来,只要关心自己用到几个参数既可以了。

    例如这样一个调用

    查看函数的汇编代码

    可以看到,对println("%d %d", 10, 20, 30, 40);的调用确实是从右往左将参数压入到栈中。


    这里还有另外一个问题是:因为可变参函数,函数定义的时候并没有定义形参原型,调用的时候怎么使用参数呢?为此,C语言定义了如下的宏:

    1. void va_start(va_list ap, last);//取第一个可变参数(如上述printf中的i)的指针给ap,last是函数声明中的最后一个固定参数(比如printf函数原型中的*fromat);
    2. type va_arg(va_list ap, type);//返回当前ap指向的可变参数的值,然后ap指向下一个可变参数;type表示当前可变参数的类型(支持的类型位int和double);
    3. void va_end(va_list ap);//将ap置为NULL

    其在头文件中的定义如下:

    1. /*
    2. * define a macro to compute the size of a type, variable or expression,
    3. * rounded up to the nearest multiple of sizeof(int). This number is its
    4. * size as function argument (Intel architecture). Note that the macro
    5. * depends on sizeof(int) being a power of 2!
    6. */
    7. #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    8. #define _VA_LIST char*
    9. typedef _VA_LIST va_list;
    10. #define va_dcl va_list va_alist;
    11. #define va_start(ap) ap = (va_list)&va_alist
    12. #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
    13. #define va_end(ap) ap = (va_list)0

    从上面的定义很容易可以看出,va_start使ap指向第一个可选参数。va_arg返回参数列表中的当前参数并使ap指向参数列表中的下一个参数。va_end则将ap置为空指针。
    关于_INTSIZEOF做一点简单的解释:因为sizeof(int)2^n,因此它的位模式必然是1...000,因此该宏会





  • 相关阅读:
    QT visual stuido 集成插件不能打开ui文件的原因
    KLSudoku 1.2 数独游戏软件发布
    QT for linux 的错误 undefined reference to 'FcFreeTypeQueryFace' 的解决方法
    tp3.2源码解析——入口文件
    关于php调用.net的web service 踩过的坑
    CentOS7 LNMP+phpmyadmin环境搭建(二、LNMP环境搭建)
    CentOS7 LNMP+phpmyadmin环境搭建(一、虚拟机及centos7安装)
    php无限分类
    php的文件引用
    CentOS7 LNMP+phpmyadmin环境搭建(三、安装phpmyadmin)
  • 原文地址:https://www.cnblogs.com/joyzhuang/p/4025270.html
Copyright © 2011-2022 走看看