2010-07-06 11 views
12

Eventuali duplicati:
Are there gotchas using varargs with reference parametersvarargs (va_list va_start) non funziona con il parametro passaggio per riferimento

Salve, ho un problema con varargs. Guarda il mio codice (Microsoft Visual Studio 2005 o 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; 
} 

funzione T1, T2 funzionano bene. Ma la funzione T3 ha un problema. Il puntatore p non punta "Test3". Non posso usare va_start con pass-by-reference? Grazie in anticipo.

+2

Espone il comportamento previsto in g ++, ma questo non significa molto, vero? –

risposta

13

Non è possibile utilizzare i riferimenti con va_start secondo il C++ standard 18,7/3:

Le restrizioni che ISO C posti sul secondo parametro alla macro va_start() nell'intestazione diverse nella presente norma internazionale. Il parametro parmN è l'identificativo del parametro più a destra di nell'elenco dei parametri delle variabili della definizione della funzione (quella appena prima del ...). Se il parametro parmN viene dichiarato con una funzione, array o tipo di riferimento o con un tipo non compatibile con il tipo che risulta quando si passa un argomento per il quale non esiste alcun parametro, il comportamento è non definito.

4

Risposta breve: no, non è possibile farlo.

NOTA: ho visto la prima risposta che riporta lo standard, ma credo valga la pena di mostrare anche i miei test.

va_start è definito così:

illustrato 6: #define va_start(ap,v) (ap = (va_list)&v + _INTSIZEOF(v))

illustrato 8: #define _crt_va_start(ap,v) (__va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), \ __alignof(v), _ADDRESSOF(v)))

Con questo codice:

#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; 
} 

uscita

char ref:1 
int ref:4 

Poiché a livello di implementazione i riferimenti vengono passati sullo stack in modo simile ai puntatori questo rappresenta un problema poiché la dimensione differisce (è a causa della macro che calcola la dimensione del tipo non tenendo conto che il parametro è in realtà un riferimento, che non è costante ma dipende dalla dimensione effettiva del tipo).

+1

Grazie. È interessante. :) –

Problemi correlati