2009-05-10 18 views
5

vorrei inizializzare un array di struct, con lo stesso elemento ripetutamente, cioèinitializng una matrice C con i dati ripetitivi

struct st ar[] = { {1,2}, {1,2}, {1,2} }; 

Comunque io non voglio correre alcun codice per questo, mi auguro che il il layout della memoria al momento dell'esecuzione del programma sarebbe come tale, senza le istruzioni della CPU coinvolte (aumenterebbe il tempo di avvio su CPU molto lente e array relativamente grandi).

Questo ha senso, quando si utilizza la matrice come mini banca dati ad hoc (mappe id a struct) e quando si desidera utilizzare un valore di default a tutti i valori di database.

La mia soluzione migliore era quella di usare qualcosa di forma

#define I {1,2} 
struct st ar[SIZE_OF_ARRAY] = { I,I,I }; 

modo che il compilatore mi avvisa se sto avendo troppo o troppo poco I s. Ma questo è lontano dall'ideale.

Penso che ci sia alcuna soluzione per questo in ANSI-C, ma ho pensato che forse c'è un macro-abusi, o estensione gcc che avrebbe fatto il lavoro. Idealmente mi piacerebbe una soluzione standard, ma basterebbero anche quelli specifici del compilatore.

Ho pensato che in qualche modo sarei stato in grado di definire una macro in modo ricorsivo in modo che I(27) sarebbe stato risolto in 27 {1,2} s, ma non credo sia possibile. Ma forse mi sbaglio, c'è qualche trucco per quello?

Forse l'assemblaggio in linea farebbe il trucco? Sarebbe molto facile definire tale layout di memoria con MASM o TASM, ma non sono sicuro che sia possibile incorporare le istruzioni di layout della memoria all'interno del codice C.

C'è qualche trucco linker che attirarlo per inizializzare la memoria secondo i miei ordini?

PS I know Posso generare automaticamente il file C con qualche script. L'uso di script personalizzati non è desiderabile. Se usassi uno script personalizzato, inventerei una macro C REP(count,exp,sep) e scriverei un preprocessore mini-C per sostituirlo con exp sep exp sep ... exp {exp appears count time}.

risposta

10

Il boost preprocessor library (che funziona bene per C) potrebbe aiutare.

#include <boost/preprocessor/repetition/enum.hpp> 

#define VALUE(z, n, text) {1,2} 

struct st ar[] = { 
    BOOST_PP_ENUM(27, VALUE, _) 
}; 

#undef VALUE 

Se si desidera utilizzarlo, ti basta la directory boost/preprocessor dalla spinta - è del tutto autonomo.

Sebbene abbia alcuni limiti arbitrari sul numero di elementi (penso che siano in questo caso 256 ripetizioni). Esiste un'alternativa denominata chaos che non lo è, ma è sperimentale e funzionerà solo per i preprocessori che seguono esattamente lo standard (GCC fa).

+0

Sì, BPP sembra piuttosto ideale per questa cosa. – Macke

+0

Una buona soluzione standard - grazie. –

0

Quello che hai in forma di I s è il miglior standard C può dare. Non capisco come si possa essere contrari al codice di inizializzazione standard, ma va bene con il montaggio. L'assemblaggio di incorporamento è necessariamente un meccanismo non portatile non standard.

Il problema con le macro ricorsive è che non si saprebbe dove fermarsi.

+0

Come detto, aggiungendo codice di inizializzazione può rallentare il tempo di avvio. Comunque l'ASM in linea è cattivo, poiché non è standard, tuttavia fornirebbe il comportamento esatto che desidero dal codice: la memoria preinizializzata. Quindi, per riassumere, ASM è non portabile ma fornisce il risultato desiderato, il codice di inizializzazione è standard, ma fornisce un risultato diverso che non è sempre accettabile. –

5

Il modo più semplice che posso pensare è quello di scrivere uno script per generare gli inizializzatori che è possibile includere nel codice C:

{1,2}, 
{1,2}, 
{1,2} 

Poi, nel tuo fonte:

struct st ar[] = { 
    #include "init.inc" 
}; 

Puoi organizza il tuo Makefile per generare automaticamente se lo desideri.

+0

Sta parlando del codice C. Inoltre, non vedo come sia meglio che avere gli inizializzatori insieme alla definizione. Infine, penso che voglia generare automaticamente gli inizializzatori in base alle dimensioni dell'array. – dirkgently

+0

Questo può essere automatizzato, come dice Greg. Soprattutto se chiami il file include init_3.inc per 3 elementi, init_17.inc per 17, ecc. Quindi disponi di una regola makefile per creare init_ .inc per ogni n, e generare crea dipendenze con gcc -M o -MM. Quindi la fonte dice "struct st ar [] = {\ n #include" init3.inc "\ n};", e il resto è automatico. –

2

ti sto indovinando posso, sul file con la definizione matrice, ne:

#include "rep_array_autogen.c" 
struct st ar[SIZE_OF_ARRAY] = REPARRAY_DATA; 

e avere il vostro Makefile generare rep_array_autogen.c con un formato simile

#define SIZE_OF_ARRAY 3 
#define REPARRAY_DATA {{1, 2}, {1, 2}, {1, 2}, } 

Dal rep_array_autogen.c è costruito su la tua macchina, sarebbe altrettanto veloce di codificarla a mano lì dentro.

0

Elazar,

Puoi dare i dati per sostenere il vostro parere che i dati pre-inizializzati è più veloce di run-time di inizializzazione?

Se si sta eseguendo il codice su una macchina standard con Hard Disk Drive (HDD) e il programma si trova sull'HDD, quindi il tempo necessario per copiare i dati dalla sezione di dati della propria immagine binaria alla RAM è essenzialmente la stessa quantità di tempo di utilizzo di alcuni tipi di inizializzazione di runtime.

Kip Leitner

+1

Kip, ti darò ora il razionale e i dati dopo. Il razionale è, con dati nessuno-preinizializzati, il caricatore copia l'immagine binaria, che contiene le informazioni come comandi di assemblaggio (mov ax, Data). e quindi i comandi di questo assembly devono essere eseguiti nuovamente per spostare i dati nella memoria. Il che significa sul doppio lavoro. Cercherò di creare un micro-benchmark a volte presto. –

Problemi correlati