2010-12-02 25 views
21

Olası Çoğalt:
C/C++: Passing variable number of arguments around__VA_ARGS__ makro yerine bir C işlevi içinde nasıl kullanılır?

Şu anda benim C dosyada ilan aşağıdaki makro kullanıyorum.

#define COMMON_Print(...) printf (__VA_ARGS__) 

Şimdi bu çağrı sadece iyi çalışıyor, ancak ben şuna benzer bir C işlevi oluşturmak gerekiyor çıkıyor:

void COMMON_Print(...) 
{  
    printf (__VA_ARGS__); 
} 

Yani bu fonksiyon çalışmaz ben

"hata: tanımlanmamış tanımlayıcı __VA_ARGS__" bir hata alıyorum

Projemin karmaşıklığı, bir arayüz olduğundan bir fonksiyona sahip olmayı gerektiriyor ... Peki, parametreleri nasıl alabilirim ... ve bunları printf fonksiyonuna nasıl aktarabilirim? Ya da daha iyi neyi yanlış yapıyorum?

Teşekkürler!

+1

bu Bkz http://stackoverflow.com/questions/205529/cc-passing-variable-number-of-arguments: Neyse ki bunu yapar printf bir varyasyonu var, sizin fonksiyonu yazılacak bu yol var -Çevre – Kos

cevap

36

?printf işlevlerinin her biri, aynı şeyi yapan ancak va_list değişken değişken listesi içeren karşılık gelen v?printf işlevine sahiptir.

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

void COMMON_Print(char *format, ...) 
{ 
    va_list args; 

    va_start(args, format); 
    vprintf(format, args); 
    va_end(args); 
} 

Yan Not: va_start parametre olarak ... önceki son tartışmanın adını alır Bildirim söyledi. va_start, değişken bağımsız değişkenleri almak için yığın tabanlı bir büyü yapan ve bunu yapmak için son sabit bağımsız değişkenin adresini gerektiren bir makrodur.

Bunun bir sonucu olarak, en az bir sabit argüman olmalı, böylece va_start'a iletebilirsiniz. Bu yüzden daha basit COMMON_Print(...) bildirimi ile yapıştırmak yerine format argümanını ekledim.

Bkz:http://www.cplusplus.com/reference/clibrary/cstdio/vprintf/

+0

Makroları kullanırsanız, önceki bir argüme ihtiyacınız yoktur. Bu örneği ele alalım: '#define LOGI (...) ((void) __ android_log_print (ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS __)) Bu açıkça bir kullanım açısından çok uygundur. –

15

__VA_ARGS__ makrolar içindir; variadic fonksiyonları oldukça farklıdır. Bunları işlemek için va_start, va_arg ve va_end numaralarını stdarg.h'dan kullanmanız gerekir.

void COMMON_Print(const char* fmt, ...) 

Sonra bir va_list tanımlamak ve ayarlamak için va_start kullanabilirsiniz::

va_list args; 
va_start(args, fmt); 
// your code here 
va_end(args); 

Artık şunlara args kullanabilirsiniz

İlk olarak, fonksiyon en az bir adlandırılmış parametre, örneğin ihtiyacı argümanlara erişmek; va_arg(args, TYPE) numaralı telefonu arayarak, bir sonraki varyasyon argümanını döndürecek, böylece tüm argümanları okuyana kadar bunu aramaya devam edebilirsiniz.

sadece printf aramaya çalışıyorsanız

doğrudan va_list alır vprintf adında bir printf varyantı var:

vprintf(fmt, args); 

diğerinden variadic işlevi çağırmak için kolay bir yolu yoktur; Bu va_list

+0

Açıklamanız için teşekkürler. Yardım ettikleri yardım ve açıklamalar için teşekkürler! :) – Jona

+0

'va_arg (args, TYPE)' NULL ancak NULL arayan tarafından geçirilirse dönecektir. Va_arg için varsayılan son koşul yoktur. Bir sentinel değerini geçmeli veya bir parametreyle geçirilen veya printf formatı dizesindeki% sayısını hesaplayarak, tam bir parametre sayısını bilmelisiniz. –

+0

@tristopia Oh, sağa; Gerektiğinde NULL'u geçme alışkanlığımdayım. Sabit –

3

ürününe benzer bir ihtiyacınız var. Ellipsis numaralı telefon operatörü.

4

__VA_ARGS__ sadece makrolar içindir.

Argüman değişken sayısını başka bir işleve zincirleme doğrudan yapılamaz. Bunun yerine, va_list'e sahip olmanız gerekir ve çağıran işlev bir va_list almak zorunda.

void COMMON_Print(char *format,...) 
{  
    va_list args; 
    va_begin(args,format); 
    vsprintf(format,args); 
    va_end(args); 
} 
+1

Cevabınız için çok teşekkürler! Aslında çalışıyor! Ama sonunda çözmem gereken bazı biçimlendirme sorunları var. FYI, gömülü bir cihaz üzerinde çalışıyorum. – Jona

+0

vaprintf nedir? Yoksa sadece yazım hatası mı? –

İlgili konular