簡體   English   中英

在 va_list 對象中包含第一個參數

[英]Include First Argument in va_list object

是否可以在 va_list 中包含函數的第一個參數? 我想將參數從一個函數傳遞到另一個函數。

int main(){
    test(1,2,3,4,5,-1);
}

void test(int firstArg, ...){
    va_list va;
    va_start(va, firstArg);
    passFunction(va);
}

void passFunction(va_list va){
    int x;    
    while((x = va_arg(ap,int))!=-1){
        cout << x << endl;  
    }
}

我想要的輸出:

1
2
3
4
5

實際輸出:

2
3
4
5

有沒有辦法在不顯式將第一個參數傳遞給函數的情況下實現這一點?

我知道這是一個老問題,但我最近遇到了它,我想我會分享我的解決方案。 無論編譯器如何,此答案都應該有效,但會添加更多代碼。 我在 while 語句中使用第一個參數,但在使用第一個參數之前我不會調用 va_arg()。

 main () {
        test( 1, 2, 3, 4, 5, -1 );
    }

void passFunction( int one, va_list va )
{
    int x = one;
    va_list va_copy;
   
    va_copy( va_copy, va );
    while (x != -1)
    {
        std::cout << x << std::endl;
        x = va_arg( va_copy, int );        
    }
    va_end( va_copy );
}

void test( int one, ... ) const
{
    va_list va;
    va_start(va,one);
    passFunction( one, va );
    va_end(va);
}

va_start()需要一個固定參數,並將va_list初始化為指定參數之后的下一個參數。 由於您的函數只有一個固定參數,因此無法選擇使用庫存va_start()將其包含在va_list中,因為它前面沒有固定參數。

僅在32位(64位更復雜)中,您可以將va_start()編譯器源代碼從varargs.hstdargs.h (或等效代碼) stdargs.h到您自己的源文件中,然后進行調整以進行初始化帶有指定參數本身地址而不是va_arg跟地址的va_arg

例如,在C ++ Builder中, va_start()定義為:

#ifdef __cplusplus
#define va_start(ap, parmN) ((void)((ap) = (std::va_list)((char _FAR *)(&parmN)+__size(parmN))))
#else
#define va_start(ap, parmN) ((void)((ap) = (va_list)((char _FAR *)(&parmN)+__size(parmN))))
#endif

因此,您只需刪除+__size(parmN)部分:

#ifdef __cplusplus
#define my_va_start(ap, parmN) ((void)((ap) = (std::va_list)((char _FAR *)(&parmN))))
#else
#define my_va_start(ap, parmN) ((void)((ap) = (va_list)((char _FAR *)(&parmN))))
#endif

在Visual Studio中, va_start()定義為:

#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INSIZEOF(v) )
#define va_start _crt_va_start

因此,您只需刪除+ _INSIZEOF(v)部分:

#define my_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) )

GCC實際上使用編譯器固有函數而不是宏,因此您可能無法獲取其va_start()源,但是由於cdecl調用約定(唯一支持32位可變參數的調用約定)已經標准化,因此生成的代碼應該相似跨編譯器。

無論哪種方式,預處理器生成的代碼最終都會大致相同,因此,如果與編譯器兼容,則可以直接對其進行編碼:

void test(int firstArg, ...){
    va_list va = (va_list) &firstArg;
    passFunction(va);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM