深刻C語言可變參數(va_arg,va_list,va_start,va_end,_INTSIZEOF)

1、什麼是可變參數html

         在C語言編程中有時會遇到一些參數個數可變的函數,例如printf(),scanf()函數,其函數原型爲:
int printf(const char* format,…),int scanf(const char *format,…);它除了有一個參數format固定之外,後面跟着的參數的個數和類型是可變的(用三個點「…」作參數佔位符),實際調用時能夠有如下的形式:
           printf(「%d」,i);  printf(「%d,%c」,i,j);
linux

2、C語言---簡單的可變參數例子(實現思想)程序員

        一、整型數據的輸出
編程

#include <stdio.h>
#include <stdarg.h>
void ar_cnt(int cnt,...);
void ar_cst(char const *s,...);
int main(int argc, char* argv[])
{
    int in_size =_INTSIZEOF(int);
    printf("int_size=%d\n",in_size);
    ar_cnt(5,1,2,3,4);
    return 0; 
}
void ar_cnt(int cnt,...)
{
    int value1=0;
    int i=0;
    int arg_cnt = cnt;
    va_list arg_ptr;
    va_start(arg_ptr,cnt);
    for(i=0;i<cnt;i++)
    {
        value1=va_arg(arg_ptr,int);
        printf("posation %d=%d\n",value1,i+1);
    }
    va_end(arg_ptr);
}

運行結果:函數

image

        二、字符串的輸出ui

#include <stdio.h>
#include <stdarg.h>

void PrintLines(char *first,...)
{
    char *str;
    va_list v1;
    str = first;
    va_start(v1,first);
    do 
    {
        printf("%s\n",str);
        str=va_arg(v1,char*);
    } while (str != NULL );
    va_end(v1);
}

int main(int argc, char* argv[])
{
    PrintLines("First","Second","Third","Fourth",NULL);
    return 0;
}

運行結果:spa

image

           三、找出最大數.net

#include <stdio.h>
#include <stdarg.h>
int FindMax(int amount,...)
{
    int i,val,great;
    va_list v1;
    va_start(v1,amount);
    great=va_arg(v1,int);
    for(i=1;i<amount;i++)
    {
        val=va_arg(v1,int);
        great=(great>val)?great:val;
    }
    va_end(v1);
    return great;
}

int main(int argc, char* argv[])
{
    int max=FindMax(5,100,20,456,102,4,300);
    printf("The Max one is %d\n",max);
    return 0;
}

運行結果:指針

image

3、對va_arg,va_list,va_start,va_end,_INTSIZEOF剖析code

 

  • 內存對齊  #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
                 具體請參考:http://blog.csdn.net/swell624/article/details/3210779
  • 可變參數用到如下宏函數 
        <1>原型:
    void va_start(va_list arg_ptr,prev_param);

              功能:以固定參數的地址爲起點肯定變參的內存起始地址,獲取第一個參數的首地址

              返回值:無

        <2>原型:va_list 類型的變量,va_list arg_ptr ,這個變量是指向參數地址的指針,由於獲得參數的地址以後,再結合參數的類型,才能獲得參數的值。

        <3>原型:type va_arg(va_list arg_ptr,type);

              功能:獲取下一個參數的地址

            返回值:根據傳入參數類型決定返回值類型

        <4>原型:void  va_end(va_list arg_ptr);

              功能:將arg_ptr指針置0

             返回值:無

  • 使用可變參數應該有如下步驟

     ⑴在程序中將用到如下這些宏:

    void va_start( va_list arg_ptr, prev_param );

    type va_arg( va_list arg_ptr, type );

    void va_end( va_list arg_ptr );

    va在這裏是variable-argument(可變參數)的意思.

    這些宏定義在stdarg.h中,因此用到可變參數的程序應該包含這個頭文件.

    ⑵函數裏首先定義一個va_list型的變量,這裏是arg_ptr,這個變量是指向參數地址的指針.由於獲得參數的地址以後,再結合參數的類型,才能獲得參數的值。

    ⑶而後用va_start宏初始化⑵中定義的變量arg_ptr,這個宏的第二個參數是可變參數列表的前一個參數,也就是最後一個固定參數。

    ⑷而後依次用va_arg宏使arg_ptr返回可變參數的地址,獲得這個地址以後,結合參數的類型,就能夠獲得參數的值。而後進行輸出。

    ⑸設定結束條件,這裏的條件就是判斷參數值是否爲-1。注意被調的函數在調用時是不知道可變參數的正確數目的,程序員必須本身在代碼中指明結束條件。至於爲何它不會知道參數的數目,讀者在看完下面這幾個宏的內部實現機制後,天然就會明白。

 

 

3、參考文獻:
       http://www.chineselinuxuniversity.net/articles/26262.shtml

        http://www.cnblogs.com/wangyonghui/archive/2010/07/12/1776068.html

        http://www.2cto.com/kf/201204/129038.html

相關文章
相關標籤/搜索