Sto avendo una domanda di programmazione C: Voglio scrivere una funzione con liste di argomenti variabili, dove i tipi specifici di ciascun argomento non sono noti - solo la sua dimensione in byte. Ciò significa che, se voglio ottenere un parametro int, I (da qualche parte prima) definire: Ci sarà un parametro con sizeof (int), che viene gestito con una funzione di callback xyz.va_list con nomi di tipi sconosciuti - solo la dimensione del byte è nota!
La mia funzione argomento variabile dovrebbe ora raccogliere tutte le informazioni dal suo richiamo, le operazioni specifiche del tipo di dati reali (che possono essere anche tipi di dati definiti dall'utente) vengono elaborate solo tramite funzioni di richiamata.
Alle funzioni standard di va_arg, non è possibile pronunciare "ottieni un valore di X byte dalla mia lista parametri", quindi ho pensato di farlo in questo modo. Il mio tipo di dati è doppio in questo caso, ma può essere qualsiasi altro numero di byte (e anche quelli variabili).
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
int fn(int anz, ...)
{
char* p;
int i;
int j;
va_list args;
char* val;
char* valp;
int size = sizeof(double);
va_start(args, anz);
val = malloc(size);
for(i = 0; i < anz; i++)
{
memcpy(val, args, size);
args += size;
printf("%lf\n", *((double*)val));
}
va_end(args);
}
int main()
{
fn(1, (double)234.2);
fn(3, (double)1234.567, (double)8910.111213, (double)1415.161718);
return 0;
}
Funziona per me, sotto Linux (gcc). Ma la mia domanda ora è: è davvero portatile? Oppure fallirà sotto altri sistemi e compilatori?
mio approccio alternativo era quello di sostituire
memcpy(val, args, size);
args += size;
con
for(j = 0; j < size; j++)
val[j] = va_arg(args, char);
ma poi, i miei valori è andato storto.
Qualche idea o aiuto su questo?
Non puoi decidere in anticipo tutti i tipi di dati che prevedi di passare? Quindi assegnare un argomento per ognuno. Riservare il primo argomento come int che quindi indica il tipo. Il chiamante della funzione HA sapere quale tipo di dato è stato superato. Un modo più tradizionale per farlo è passare un vuoto * insieme a un argomento int, quindi lanciare l'argomento void * sul tipo di dati corretto basato sull'int (o enum). –
Questo è quello che voglio evitare. I miei tipi di dati sono noti, ma solo nelle funzioni di callback specifiche dell'utente che funzionano su questi dati. La mia funzione universale che voglio implementare dovrebbe solo costruire un nuovo oggetto dati in memoria lungo una definizione di oggetto dati. Questa definizione (che è una matrice di dichiarazioni di attributi) ha solo informazioni sulla dimensione di ciascuna variabile. – Jan