|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Mar 2008
Messaggi: 401
|
[C++][Risolto] cstdarg - Passare argomenti da una funzione all'altra
Salve a tutti.
Ho un piccolo problema con C++: ho una funzione che accetta più argomenti, e utilizzo la libreria cstdarg per prelevarli. Ho quindi una seconda funzione, che esegue le stesse operazioni della prima con qualche aggiunta. Mi chiedevo quindi se era possibile lanciare la prima funzione, dalla prima. Ho provato a passare gli argomenti in questo modo: Codice:
#include <cstdarg>
void funzioneUno(string pinco, ...){
// codice
}
void funzioneDue(string pallino, ...){
funzioneUno(pallino, ...);
//altro codice
}
Ultima modifica di agente mm8 : 26-11-2009 alle 15:06. Motivo: Problema risolto |
|
|
|
|
|
#2 |
|
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Ciao,
Non mi sono mai trovato nella necessità di fare l'operazione che descrivi, ma forse potresti modificare la funzioneUno in modo che accetti due argomenti: Codice:
void funzioneUno(string pinco, va_list lista); Codice:
void funzioneDue(string pallino,...){
va_list vl;
va_start(vl,pallino);
funzioneUno(xxx,vl);
va_end();
}
NB:La cosa è tutta da verificare, non l'ho mai sperimentata come ho detto. Ciaociao
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Mar 2008
Messaggi: 401
|
Guarda, in effetti ci avevo pensato, lo stavo sperimentando giusto ora. Grazie mille del consiglio
Edit: tutto a posto, funge. Ultima modifica di agente mm8 : 26-11-2009 alle 15:05. |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Però di fatto hai cambiato l'intestazione della funzione...e quando non lo puoi fare ?
Mettiamo caso che io voglia fare un layer aggintivo per la printf: Codice:
int myPrintf(string format, ...)
{
printf("%s\n", format.c_str());
printf(format.c_str(), ????);
}
|
|
|
|
|
|
#5 |
|
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Ciao,
Beh, senza cambiare il prototipo la vedo un po'difficile anch'io... in quel caso concordo appieno: non è possibile. Questo anche perchè i tre puntini di sospensione (...) sono un'espressione che può stare in un'intestazione o in un prototipo di funzione (in deroga alla normale sintassi <tipo> <nome variabile> per i parametri), ma non possono di certo essere passati come argomento a qualsivoglia altro metodo/funzione, né essere usati in qualsiasi espressione di qualsiasi tipo. Non a caso per ricondurli ad un insieme di variabili è necessario, nel corpo della funzione, usare una va_list e le macro va_start, va_end e va_args. Ciaociao
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator Ultima modifica di bottomap : 26-11-2009 alle 15:47. |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Ultima modifica di cionci : 26-11-2009 alle 17:23. |
|
|
|
|
|
|
#9 |
|
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Ciao,
Credo che i tre puntini e la varargs sia qualcosa di arcaico, nato ben prima dello standard ANSI C. Un header varargs.h si dovrebbe rintracciare in POSIX e rappresenta ciò da cui poi è nato stdargs.h in UNIX... credo si parli della fine degli anni 80 ed inizi degli anni 90 (sicuramente esisteva solo il C stretto, e forse siamo prima dell'ISO C e del C89). In effetti è rimasta di utilizzo piuttosto raro... personalmente credo di aver usato la cosa, per non perdere tempo nello sviluppo, una sola volta fino ad ora e di aver sentito di rado l'esigenza di un insieme indefinito di parametri - piuttosto ricorro a contenitori e tratto direttamente quelli (strada che è pienamente percorribile anche per il problema in discussione - soprattutto se gli elementi sono omogenei tra loro). Edit: Quello in link è l'header apposito di sistema (stdarg.h o cstdarg sono la stessa cosa. Nel secondo caso quello che sta dentro è stato inserito nel namespace std, niente di più)... quello che usi (implicitamente o meno) quando dichiari va_args, va_list, va_start e va_end. Ciaociao
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator Ultima modifica di bottomap : 26-11-2009 alle 17:27. |
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Io credo che risalga alla prima stesura del C, visto che la printf sfrutta questo meccanismo.
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2776
|
|
|
|
|
|
|
#12 |
|
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Si, l'origine è indubbiamente arcaica...
Per finire di condire la discussione con qualche cenno prettamente storico, ecco scovato un gustoso articolo di wiki sulle orgini e storia della printf, che tra l'altro tocca di sfuggita anche i varargs (peccato che la wiki italiana non sia mai così fornita di materiale quanto quella inglese): http://en.wikipedia.org/wiki/Printf Ciaociao
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Allora si può !!!
Bisogna passare la struttura va_list come parametro alla funzione dove ci sono i tre punti. Codice:
#include <stdio.h>
#include <stdarg.h>
void funzioneDue(int num, ...)
{
int i;
int val;
printf ("int passed: ");
va_list vl;
va_start(vl,num);
for (i=0;i<num;i++)
{
val=va_arg(vl,int);
printf ("\t%d",val);
}
va_end(vl);
printf ("\n");
}
void funzioneUno(int num, ...)
{
va_list vl;
va_start(vl, num);
funzioneDue(num, vl);
va_end(vl);
}
int main()
{
funzioneUno(5, 1, 5, 2, 3, 4);
}
Ultima modifica di cionci : 26-11-2009 alle 18:34. |
|
|
|
|
|
#14 |
|
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Ciao,
No... ci avevo pensato anch'io, ma non ottieni la cosa voluta. Compila correttamente solo perché a funzioneDue puoi passare quello che vuoi (in virtù appunto dei ...). vl sarà un argomento come gli altri (un int, un char)... certo lo puoi trattare come tale in funzioneDue se sai che ti arriva come secondo parametro, ma così non ci scostiamo dal problema originale. Nella va_list della funzioneDue avrai semplicemente un va_args che contiene una va_list (della funzioneUno), tutto qui. Poi forse ci si può giocare un po'sopra se si riesce ad individuare il tipo del dato e/o se si conosce la posizione esatta del dato nella seconda lista. La discussione su vprintf e simili funzioni aveva tratto in inganno anche me. In realtà la frase "These functions offer the ability for programmers to essentially create their own printf variants" è un po'ambigua. Significa che con una lista di argomenti variabili puoi ottenere la va_list e che, usando la vprintf/vsprintf/vfprintf puoi stampare a video/su stringa/su file (in virtù del fatto che vprintf ha una va_list come argomento - in sostanza quanto avevo proposto all'inizio nella modifica del prototipo di funzioneDue) e di conseguenza ottenere una "tua" versione della printf. Edit:Ho fatto comunque qualche test a scanso di equivoci (MSVC .NET 2003 Standard) e ottengo risultati piuttosto randomici. Da debugger vedo anche che il primo elemento della va_list di funzioneDue è (come mi aspettavo) un puntatore alla va_list di funzioneUno. Ciaociao
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator Ultima modifica di bottomap : 26-11-2009 alle 19:00. |
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
Se a te e' venuto fuori 2 3 4 e' probabilmente dovuto al fatto che sfori e vai a pescare nello stack frame della chiamata precedente (ma e' solo una mia ipotesi). L'unico modo portabile secondo me e' quello di contare il numero di argomenti e chiamarlo esplicitamente. In questo caso ovviamente bisogna mettere un limite al numero massimo di argomenti, ma con un po' di giochi di template si puo' probabilmente lasciarlo ragionevolmente alto senza dover diventar matti a scrivere tutto a mano.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
|
#16 | |
|
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Quote:
Ciaociao
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator |
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quasi sicuramente...secondo me comunque qualcosa si può fare... Ci penso un po'.
|
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Allora...lavorando in asm non ci dovrebbero essere grossi problemi.
Infatti si rifà nuovamente il push nello stack dei parametri, conoscendone la dimensione e il numero è semplicissimo. In C non mi viene in mente una soluzione valida, questo perché bisognerebbe passare come parametro alla funzione una struttura dati con la parte dati allocata staticamente, in quanto se fosse allocata dinamicamente verrebbe passata per puntatore. In C++ si potrebbe fare qualcosa con i template. |
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Giusto per farvi capire... Questo non funziona perché a viene passato per indirizzo.
Codice:
#include <stdio.h>
#include <stdarg.h>
void funzioneDue(int num, ...)
{
va_list vl;
va_start(vl, num);
for(int i = 0; i < num; ++i)
{
printf("%d ", va_arg(vl, int));
}
va_end(vl);
printf("\n");
}
void funzioneUno(int num, ...)
{
int a[num];
va_list vl;
va_start(vl, num);
for(int i = 0; i < num; ++i)
{
a[i] = va_arg(vl, int);
}
va_end(vl);
funzioneDue(num, a);
}
int main()
{
funzioneUno(5, 12, 13, 154, 123, 222);
return 0;
}
Ultima modifica di cionci : 26-11-2009 alle 21:31. |
|
|
|
|
|
#20 |
|
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Ciao,
Mi pare che stiamo uscendo un po dal seminato... in asm la cosa è chiaramente fattibile, ma viste le prerogative del C non hai molte alternative a disposizione... Se vuoi (e bisogna vedere quanto e se è fattibile) basterebbe qualcosa del genere, ma fa affidamento che il va_list sia il primo argomento passato, quando invece il placeholder "..." è assolutamente generico e non ti assicura niente sull'ordine dei parametri: Codice:
... va_list v1; va_start(v1,x); va_list v2=va_arg(v1,va_list); ... e a questo punto girare v2 ... va_end(v1); Ciaociao
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator Ultima modifica di bottomap : 26-11-2009 alle 21:30. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 13:48.




















