C傳遞可變參數(shù)

C傳遞可變參數(shù)

va_list

??va_list配合va_start/va_arg/va_end宏定義, 可以完成C語言中可變參數(shù)的傳遞獲取. 需要注意的是, 必須有一個(gè)固定參數(shù); 其次三個(gè)宏的使用必須嚴(yán)格一致。

示例

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

void test1(int n, ...)
{
    va_list ap;
    va_start(ap, n);
    const char *tmp = NULL;

    for(int i = 0; i < n; i++)
    {
        tmp = va_arg(ap, const char*);
        if(tmp)
        {
            printf("%s  ", tmp);
        }
    }
}

int main()
{
    test1(3, "a", "b", "c", "d");

    return 0;
}

結(jié)果

a  b  c  

注意事項(xiàng)

  • 1 我們通常使用第一個(gè)值作為可變參數(shù)的個(gè)數(shù); 但是實(shí)際中我們?cè)俸瘮?shù)內(nèi)無法得到傳遞的參數(shù)個(gè)數(shù), 我們可以無限制的調(diào)用va_arg, 假設(shè)我們將循環(huán)次數(shù)改為4次, 最后一次獲取的值是不確定的, 如下是亂碼.
a  b  c ?(
  • 2 這個(gè)函數(shù)的使用是不嚴(yán)格且不安全的

自己實(shí)現(xiàn)可變參數(shù)傳遞

??首先我們需要明白函數(shù)入棧的規(guī)則, 函數(shù)參數(shù)入棧從右到左; 如果我們知道第一個(gè)參數(shù)的地址并且知道參數(shù)的類型, 我們就可以得到其余參數(shù)的地址了. 這就是va_list需要一個(gè)固定參數(shù)的原因, 如果沒有該固定參數(shù)我們是無法進(jìn)行任何操作的.

參數(shù)類型是否必須一致?

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

void func(int a, ...)
{

}

void main()
{
    int a = 10;
    short b = 10;
    printf("sizeof int: %d\n", sizeof(int));
    printf("sizeof ptr: %d\n", sizeof(char*));
    printf("sizeof short: %d\n", sizeof(short));
    func(a, "hello", b, "world");
}

結(jié)果是:

sizeof int: 4
sizeof ptr: 4
sizeof short: 2

可以成功編譯通過并執(zhí)行, 可以得知編譯器內(nèi)部并沒有做特別詳細(xì)的判斷和區(qū)分; 那么就會(huì)引入一個(gè)新的問題, 由于不同類型的字節(jié)數(shù)不同, 會(huì)不會(huì)產(chǎn)生字節(jié)對(duì)齊的問題?

會(huì)不會(huì)產(chǎn)生字節(jié)對(duì)齊?

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

void func(int a, ...)
{
    const char *argv = (const char *)&a;                    //指向棧的指針

    int Arg1 = a;
    printf("Arg[1]: %d\n", Arg1);

    const char *Arg2 = *(const char **)(argv + 4);          
    //將指向棧中第二個(gè)參數(shù)的指針轉(zhuǎn)換為為指向字符串指針的指針, 再進(jìn)行解引用就可以獲得棧中的字符串指針

    printf("arg[2]: %s\n", Arg2);

    short Arg3 = *(short*)(argv + 8);
    printf("arg[3]: %d\n", Arg3);

    const char *Arg4 = *(const char**)(argv + 12);
    printf("arg[4]: %s\n", Arg4);
}

void main()
{
    int a = 10;
    short b = 100;
    printf("sizeof int: %d\n", sizeof(int));
    printf("sizeof ptr: %d\n", sizeof(char*));
    printf("sizeof short: %d\n", sizeof(short));
    func(a, "hello", b, "world");
}

結(jié)果:

sizeof int: 4
sizeof ptr: 4
sizeof short: 2
Arg[1]: 10
arg[2]: hello
arg[3]: 100
arg[4]: world

結(jié)論: 產(chǎn)生了字節(jié)對(duì)齊

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容