2010-07-06 31 views
12

mümkün Yinelenen çalışmaz:
Are there gotchas using varargs with reference parametersvarargs geçiş referans-ile-parametresi

Merhaba, varargs ile ilgili bir sorun vardır. Koduma bakın (Microsoft Visual Studio 2005 veya 2008).

#include <stdarg.h> 

struct Test { int a; }; 

void T1(int n, ...) { 
va_list args; 
va_start(args, n); 
char* p = va_arg(args, char*); 
va_end(args); 
} 

void T2(Test n, ...) { 
va_list args; 
va_start(args, n); 
char* p = va_arg(args, char*); 
va_end(args); 
} 

void T3(const Test& n, ...) { 
va_list args; 
va_start(args, n); 
char* p = va_arg(args, char*); // p corrupt!! 
va_end(args); 
} 

int _tmain(int argc, _TCHAR* argv[]) { 
const Test t; 
T1(1, "Test1"); 
T2(t, "Test2"); 
T3(t, "Test3"); 
return 0; 
} 

işlev T1, T2 iyi çalışır. Ancak T3 fonksiyonunun bir problemi var. İşaretçi p "Test3" işaret etmez. Va_start'ı referans ile kullanamaz mıyım? Şimdiden teşekkürler.

+2

Amaçlanan davranışı g ++ olarak gösterir, ancak bu gerçekten çok fazla bir şey ifade etmez, değil mi? –

cevap

13

Sen C++ Standard 18.7/3'e göre va_start ile başvurular kullanamazsınız: başlığındaki yılında va_start() makro ikinci parametreye ISO C yerlerde bu standardın farklıdır

kısıtlamalar. ParmN parametresi, işlev tanımının değişken parametre listesinde en sağdaki parametresinin tanımlayıcısıdır (...). ParmN parametresi bir işlev, dizi veya başvuru türü veya uyumlu olmayan bir türle ile bildirilmemişse, hiçbir parametre bulunmayan bir bağımsız değişken iletilirken bu davranış undefined olur. Kısa yanıt: Hayır, bunu yapamazsınız.

4

NOT: Standardı belirten ilk cevabı gördüm ama aynı zamanda testlerimi göstermeye değdiğini düşünüyorum.

va_start Bu aşağıdaki gibi tanımlanır:

Görsel 6: #define va_start(ap,v) (ap = (va_list)&v + _INTSIZEOF(v))

Görsel 8: Bu kod ile #define _crt_va_start(ap,v) (__va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), \ __alignof(v), _ADDRESSOF(v)))

:

#include <cstdio> 

int main() 
{ 
    char c; 
    char &rc = c; 
    int i; 
    int &ri = i; 

    printf("char ref:%d\n", sizeof(rc)); 
    printf("int ref:%d\n", sizeof(ri)); 

    return 0; 
} 

çıkış

char ref:1 
int ref:4 

Uygulama düzeyinde başvurular, yığınlar için benzer bir şekilde işaretçilerden geçirildiği için, boyut farklı olduğu için bu bir sorun teşkil eder (bunun nedeni, parametrenin aslında bir parametre olduğunu dikkate almayan türün boyutunu hesaplayan makronun nedenidir) Sabit olmayan, ancak türün gerçek boyutuna bağlı olan referans).

+1

Teşekkürler. İlginç. :) –

İlgili konular