Come inizializzare tutti i membri di un array sullo stesso valore?


968

Ho un grande array in C (non in C ++ se questo fa la differenza). Voglio inizializzare tutti i membri dello stesso valore.

Potrei giurare che una volta conoscevo un modo semplice per farlo. Potrei usare memset()nel mio caso, ma non c'è un modo per farlo che sia integrato nella sintassi C?


16
Nessuna delle risposte menziona finora la notazione di inizializzatore designata che è fattibile con C99 e successive. Ad esempio: enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };e struct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };. Se si rimuovono i puntini di sospensione , questi frammenti vengono compilati in C99 o C11.
Jonathan Leffler,

In realtà la risposta di abelenky sta usando l'inizializzatore designato, ma non è un codice di inizializzazione completamente formato
Rob11311,

memset () può aiutare, ma dipende dal valore.
Nick,

2
memset()discussione specifica: stackoverflow.com/questions/7202411/… Penso che funzioni solo per 0.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Risposte:


1239

A meno che quel valore sia 0 (nel qual caso è possibile omettere una parte dell'inizializzatore e gli elementi corrispondenti verranno inizializzati su 0), non esiste un modo semplice.

Non trascurare l'ovvia soluzione, però:

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };

Gli elementi con valori mancanti verranno inizializzati su 0:

int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...

Quindi questo inizializzerà tutti gli elementi su 0:

int myArray[10] = { 0 }; // all elements 0

In C ++, anche un elenco di inizializzazione vuoto inizializzerà ogni elemento su 0. Ciò non è consentito con C:

int myArray[10] = {}; // all elements 0 in C++

Ricorda che gli oggetti con durata di archiviazione statica verranno inizializzati su 0 se non viene specificato alcun inizializzatore:

static int myArray[10]; // all elements 0

E che "0" non significa necessariamente "all-bit-zero", quindi usare quanto sopra è meglio e più portatile di memset (). (I valori in virgola mobile verranno inizializzati su +0, i puntatori su valore null, ecc.)


27
Leggendo lo standard C ++, puoi anche fare int array [10] = {}; azzerare l'inizializzazione. Non ho lo standard C per verificare che anche questo sia valido.
workmad3,

54
Guardando la sezione 6.7.8 Inizializzazione dello standard C99, non sembra che sia consentito un elenco di inizializzatori vuoto.
Jonathan Leffler,

7
C99 ha molte belle funzioni per l'inizializzazione della struttura e dell'array; l'unica caratteristica che non ha (ma Fortran IV, 1966, aveva) è un modo per ripetere un particolare inizializzatore per un array.
Jonathan Leffler,

8
@CetinSert: cosa vuoi dire che non funziona? Fa esattamente ciò che questa risposta dice che dovrebbe fare. Non fa ciò che dice il commento nel tuo codice, ma quel commento è sbagliato.
Benjamin Lindley,

9
@CetinSert: sei l'unico che ha affermato, in quel commento, che tutti gli elementi sarebbero stati impostati su -1. Questa risposta afferma, giustamente, che tutti gli elementi non specificati vengono impostati su zero. I risultati del tuo codice sono in accordo con questa affermazione.
Benjamin Lindley,

394

Se il tuo compilatore è GCC puoi utilizzare la sintassi seguente:

int array[1024] = {[0 ... 1023] = 5};

Scopri la descrizione dettagliata: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html


12
E quella sintassi provoca un enorme aumento delle dimensioni del file dei binari compilati. Per N = 65536 (anziché 1024), i miei salti binari da 15 KB a 270 KB di dimensioni !!
Cetin Sert

50
Il compilatore @CetinSert deve aggiungere 65536 ints ai dati statici, che sono 256 K, esattamente l'aumento di dimensione che hai osservato.
qrdl

15
@CetinSert Perché dovrei? È un comportamento del compilatore standard, non specifico per gli inizializzatori designati. Se si inizializzano staticamente 65536 ints, come int foo1 = 1, foo2 = 1, ..., foo65536 =1;si otterrà lo stesso aumento di dimensioni.
qrdl

27
meglio ancora: "int array [] = {[0 ... 1023] = 5}", la dimensione dell'array verrà automaticamente impostata su 1024, più facile e sicura da modificare.
Francois,

4
@Francois o per un array 2d bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}, anche se non sono sicuro che sia più leggibile rispetto al modulo completo.
g33kz0r,

178

Per inizializzare staticamente un array di grandi dimensioni con lo stesso valore, senza più copia-incolla, è possibile utilizzare le macro:

#define VAL_1X     42
#define VAL_2X     VAL_1X,  VAL_1X
#define VAL_4X     VAL_2X,  VAL_2X
#define VAL_8X     VAL_4X,  VAL_4X
#define VAL_16X    VAL_8X,  VAL_8X
#define VAL_32X    VAL_16X, VAL_16X
#define VAL_64X    VAL_32X, VAL_32X

int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X };

Se è necessario modificare il valore, è necessario effettuare la sostituzione in un solo posto.

Modifica: possibili estensioni utili

(per gentile concessione di Jonathan Leffler )

Puoi facilmente generalizzare questo con:

#define VAL_1(X) X
#define VAL_2(X) VAL_1(X), VAL_1(X)
/* etc. */

Una variante può essere creata usando:

#define STRUCTVAL_1(...) { __VA_ARGS__ }
#define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__)
/*etc */ 

che funziona con strutture o matrici composte.

#define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__)

struct Pair { char key[16]; char val[32]; };
struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") };
int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) };

i nomi delle macro sono negoziabili.


12
Lo considererei solo in casi estremi, sicuramente un memset è il modo più elegante per esprimerlo.
u0b34a0f6ae,

47
Se i dati devono essere compatibili con la ROM, memset non può essere utilizzato.
contratto del Prof. Falken ha violato il

9
Il preprocessore genererà effettivamente il codice da #defines. Con dimensioni dell'array più grandi, la dimensione dell'eseguibile aumenta. Ma sicuramente + per l'idea;)
Leonid,

7
@Alcott, su vecchi computer e ancora su molti sistemi embedded, il codice viene infine inserito in una EPROM o ROM . La ROM in grado di significare anche, nei sistemi embedded, "codice messo in flash", perché ha circa le stesse implicazioni, vale a dire che la memoria non può essere scritta in fase di esecuzione. Cioè memset o qualsiasi altra istruzione per aggiornare o cambiare memoria non può essere usata. Le costanti, tuttavia, possono essere espresse e visualizzate in flash o modificate in ROM prima dell'avvio del programma.
contratto del Prof. Falken è stato violato l'

4
@ u0b34a0f6ae: tieni presente che puoi utilizzare questo metodo anche se VAL_1Xnon è un singolo numero intero ma un elenco. Come gli stati Amigable, questa è anche la strada da percorrere per i sistemi embedded in cui si desidera definire i valori di inizializzazione di una memoria EEPROM o Flash. In entrambi i casi non puoi usare memset().
Martin Scharrer,

63

Se vuoi assicurarti che ogni membro dell'array sia inizializzato esplicitamente, ometti la dimensione dalla dichiarazione:

int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Il compilatore dedurrà la dimensione dall'elenco di inizializzatori. Sfortunatamente, per le matrici multidimensionali è possibile omettere solo la dimensione più esterna:

int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };

va bene, ma

int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };

non è.


è corretto ? int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Praveen Gowda IV,

10
No. Stai omettendo la dimensione più interna, che non è consentita. Questo darà un errore del compilatore.
Frank Szczerba,

4
Sia gli inizializzatori che l'inferenza di lunghezza sono stati introdotti in C99.
Palec,

3
@Palec: No - l'inferenza di lunghezza è stata in C fin dai tempi della C pre-standard (da quando è stata pubblicata la prima edizione di K&R, e probabilmente un po 'prima). Gli inizializzatori designati erano nuovi in ​​C99, ma questo non utilizza inizializzatori designati.
Jonathan Leffler,

53

Ho visto del codice che utilizzava questa sintassi:

char* array[] = 
{
    [0] = "Hello",
    [1] = "World"
};   

Il punto in cui diventa particolarmente utile è se stai creando un array che utilizza enum come indice:

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

#define _ITEM(x) [x] = #x

char* array[] = 
{
    _ITEM(ERR_OK),
    _ITEM(ERR_FAIL),
    _ITEM(ERR_MEMORY)
};   

Ciò mantiene le cose in ordine, anche se ti capita di scrivere alcuni dei valori enum fuori ordine.

Maggiori informazioni su questa tecnica sono disponibili qui e qui .


8
Questa è la sintassi dell'inizializzatore C99, già coperta da alcune delle altre risposte. Potresti fare utilmente la dichiarazione, char const *array[] = { ... };o addirittura char const * const array[] = { ... };, no?
Jonathan Leffler,

22
int i;
for (i = 0; i < ARRAY_SIZE; ++i)
{
  myArray[i] = VALUE;
}

Penso che sia meglio di

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5...

in caso di modifica delle dimensioni dell'array.


12
Per la cronaca, che è fondamentalmente solo un più lento, più prolisso versionememset(myArray, VALUE, ARRAY_SIZE);
Benson

18
Come useresti memset per inizializzare un array int su un valore maggiore di 255? memset funziona solo se l'array ha una dimensione in byte.
Matt,

21
@Benson: non è possibile sostituire il codice sopra con memset su piattaforme in cui sizeof (int)> sizeof (char). Provalo.
ChrisWue,

13

Puoi fare tutto l'inizializzatore statico come descritto sopra, ma può essere un vero peccato quando cambiano le dimensioni dell'array (quando l'array si attiva, se non aggiungi gli inizializzatori extra appropriati ottieni spazzatura).

memset ti dà un hit di runtime per fare il lavoro, ma nessun hit di dimensione del codice fatto correttamente è immune alle modifiche della dimensione dell'array. Vorrei usare questa soluzione in quasi tutti i casi in cui l'array era più grande, diciamo, di alcune dozzine di elementi.

Se fosse davvero importante che l'array fosse dichiarato staticamente, scriverei un programma per scrivere il programma per me e renderlo parte del processo di compilazione.


Potresti aggiungere qualche esempio sull'uso di memsetinizializzare l'array?
Sopalajo de Arrierez,

8

Ecco un altro modo:

static void
unhandled_interrupt(struct trap_frame *frame, int irq, void *arg)
{
    //this code intentionally left blank
}

static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = {
    [0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL},
};

Vedere:

C-Estensioni

Inits designati

Quindi fai la domanda: quando si possono usare le estensioni C?

L'esempio di codice sopra riportato è in un sistema incorporato e non vedrà mai la luce da un altro compilatore.


6

Per inizializzare tipi di dati "normali" (come gli array int), puoi usare la notazione parentesi, ma azzererà i valori dopo l'ultimo se c'è ancora spazio nell'array:

// put values 1-8, then two zeroes
int list[10] = {1,2,3,4,5,6,7,8};

5

Se l'array risulta essere int o qualcosa con la dimensione di int o la dimensione del tuo modello mem si adatta ai tempi esatti in un int (cioè tutti gli zero o 0xA5A5A5A5), il modo migliore è usare memset () .

Altrimenti chiama memcpy () in un ciclo che sposta l'indice.


5

Una risposta leggermente ironica; scrivi la dichiarazione

array = initial_value

nel tuo linguaggio preferito compatibile con array (il mio è Fortran, ma ce ne sono molti altri) e collegalo al tuo codice C. Probabilmente vorresti metterlo a posto per essere una funzione esterna.


4

Esiste un modo rapido per inizializzare array di qualsiasi tipo con un determinato valore. Funziona molto bene con array di grandi dimensioni. L'algoritmo è il seguente:

  • inizializza il primo elemento dell'array (modo normale)
  • copia parte che è stata impostata in parte che non è stata impostata, raddoppiando le dimensioni con ogni successiva operazione di copia

Per 1 000 000gli intarray di elementi è 4 volte più veloce della normale inizializzazione del loop (i5, 2 core, 2,3 GHz, memoria 4GiB, 64 bit):

loop runtime 0.004248 [seconds]

memfill() runtime 0.001085 [seconds]


#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 1000000

void memfill(void *dest, size_t destsize, size_t elemsize) {
   char   *nextdest = (char *) dest + elemsize;
   size_t movesize, donesize = elemsize;

   destsize -= elemsize;
   while (destsize) {
      movesize = (donesize < destsize) ? donesize : destsize;
      memcpy(nextdest, dest, movesize);
      nextdest += movesize; destsize -= movesize; donesize += movesize;
   }
}    
int main() {
    clock_t timeStart;
    double  runTime;
    int     i, a[ARR_SIZE];

    timeStart = clock();
    for (i = 0; i < ARR_SIZE; i++)
        a[i] = 9;    
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("loop runtime %f [seconds]\n",runTime);

    timeStart = clock();
    a[0] = 10;
    memfill(a, sizeof(a), sizeof(a[0]));
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("memfill() runtime %f [seconds]\n",runTime);
    return 0;
}

2
Siamo spiacenti, ma questo non è vero. Forse hai dimenticato di attivare l'ottimizzazione della compilazione durante i test (testato con la modalità debug?). Se lo provo, il loop è quasi sempre il 50% più veloce di memfill ("sempre" a causa di alcuni jitter di carico sulla mia macchina). E usando memset (a, 0, sizeof (a)); è addirittura due volte più veloce del loopfill.
RS1980,

2
Come con qualsiasi codice di benchmarking, devi essere estremamente attento. L'aggiunta di un loop per eseguire il codice di temporizzazione 10 volte (e raddoppiando la dimensione dell'array a 20 M) mostra - per me, in esecuzione su un MacBook Pro con macOS Sierra 10.12.3 e usando GCC 6.3.0 - che la prima volta, usando il ciclo impiega circa 4600 µs, mentre il memfill()codice dura circa 1200 µs. Tuttavia, nelle successive iterazioni, il ciclo impiega circa 900-1000 µs mentre il memfill()codice impiega 1000-1300 µs. La prima iterazione è probabilmente influenzata dal tempo necessario per riempire la cache. Invertire i test ed memfill()è lento la prima volta.
Jonathan Leffler,

2

Nessuno ha menzionato l'ordine dell'indice per accedere agli elementi dell'array inizializzato. Il mio codice di esempio fornirà un esempio illustrativo.

#include <iostream>

void PrintArray(int a[3][3])
{
    std::cout << "a11 = " << a[0][0] << "\t\t" << "a12 = " << a[0][1] << "\t\t" << "a13 = " << a[0][2] << std::endl;
    std::cout << "a21 = " << a[1][0] << "\t\t" << "a22 = " << a[1][1] << "\t\t" << "a23 = " << a[1][2] << std::endl;
    std::cout << "a31 = " << a[2][0] << "\t\t" << "a32 = " << a[2][1] << "\t\t" << "a33 = " << a[2][2] << std::endl;
    std::cout << std::endl;
}

int wmain(int argc, wchar_t * argv[])
{
    int a1[3][3] =  {   11,     12,     13,     // The most
                        21,     22,     23,     // basic
                        31,     32,     33  };  // format.

    int a2[][3] =   {   11,     12,     13,     // The first (outer) dimension
                        21,     22,     23,     // may be omitted. The compiler
                        31,     32,     33  };  // will automatically deduce it.

    int a3[3][3] =  {   {11,    12,     13},    // The elements of each
                        {21,    22,     23},    // second (inner) dimension
                        {31,    32,     33} };  // can be grouped together.

    int a4[][3] =   {   {11,    12,     13},    // Again, the first dimension
                        {21,    22,     23},    // can be omitted when the 
                        {31,    32,     33} };  // inner elements are grouped.

    PrintArray(a1);
    PrintArray(a2);
    PrintArray(a3);
    PrintArray(a4);

    // This part shows in which order the elements are stored in the memory.
    int * b = (int *) a1;   // The output is the same for the all four arrays.
    for (int i=0; i<9; i++)
    {
        std::cout << b[i] << '\t';
    }

    return 0;
}

L'output è:

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

11      12      13      21      22      23      31      32      33

4
<iostream>non è valido in Cquanto std::cout, std::cinecc. è parte di std::namespacee Cnon supporta namespaces. Prova invece <stdio.h>a usare per printf(...).
Francis Cugler,

2

Superando tutte le chiacchiere, la risposta breve è che se si attiva l'ottimizzazione in fase di compilazione non si farà meglio di così:

int i,value=5,array[1000]; 
for(i=0;i<1000;i++) array[i]=value; 

Bonus aggiunto: il codice è in realtà leggibile :)


7
La domanda ha richiesto specificamente l'inizializzazione. Questo non è esplicitamente inizializzazione, ma assegnazione eseguita dopo l' inizializzazione. Potrebbe essere fatto immediatamente, ma non è ancora inizializzazione.
Andy,

Completamente non utile per una grande tabella di ricerca statica all'interno di una funzione chiamata più volte.
Martin Bonner supporta Monica il

... non ricordare che le tabelle di ricerca statica all'interno delle funzioni fanno parte della domanda originale: mantienila semplice. Detto questo, @Community probabilmente l'ha inchiodato.
JWDN

1
  1. Se l'array è dichiarato statico o globale, tutti gli elementi dell'array hanno già il valore predefinito predefinito 0.
  2. Alcuni compilatori impostano l'array come predefinito su 0 in modalità debug.
  3. È facile impostare il valore predefinito su 0: int array [10] = {0};
  4. Tuttavia, per altri valori, devi usare memset () o loop;

esempio: int array [10]; memset (array, -1, 10 * sizeof (int));


0
#include<stdio.h>
int main(){
int i,a[50];
for (i=0;i<50;i++){
    a[i]=5;// set value 5 to all the array index
}
for (i=0;i<50;i++)
printf("%d\n",a[i]);
   return 0;
}

Darà la / 5 5 5 5 5 5 5 ...... fino alla dimensione dell'intero array


0

So che l'utente ha Tarskirisposto a questa domanda in modo simile, ma ho aggiunto alcuni dettagli in più. Perdona un po 'della mia C perché sono un po' arrugginito perché sono più propenso a voler usare il C ++, ma qui va.


Se conosci in anticipo le dimensioni dell'array ...

#include <stdio.h>

typedef const unsigned int cUINT;
typedef unsigned int UINT;

cUINT size = 10;
cUINT initVal = 5;

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal );
void printArray( UINT* myArray ); 

int main() {        
    UINT myArray[size]; 
    /* Not initialized during declaration but can be
    initialized using a function for the appropriate TYPE*/
    arrayInitializer( myArray, size, initVal );

    printArray( myArray );

    return 0;
}

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ) {
    for ( UINT n = 0; n < size; n++ ) {
        myArray[n] = initVal;
    }
}

void printArray( UINT* myArray ) {
    printf( "myArray = { " );
    for ( UINT n = 0; n < size; n++ ) {
        printf( "%u", myArray[n] );

        if ( n < size-1 )
            printf( ", " );
    }
    printf( " }\n" );
}

Ci sono alcune avvertenze sopra; uno è che UINT myArray[size];non viene inizializzato direttamente al momento della dichiarazione, tuttavia il blocco di codice o la chiamata di funzione immediatamente successiva inizializza ogni elemento dell'array con lo stesso valore desiderato. L'altro avvertimento è che dovresti scriverne uno initializing functionper ognuno typeche sosterrai e dovresti anche modificare la printArray()funzione per supportare quei tipi.


Puoi provare questo codice con un comparatore online trovato qui .


0

Per l'inizializzazione ritardata (ovvero l'inizializzazione del costruttore del membro della classe) considerare:

int a[4];

unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
  a[i] = 0;

0

So che la domanda originale menziona esplicitamente C e non C ++, ma se tu (come me) sei venuto qui alla ricerca di una soluzione per array C ++, ecco un trucco chiaro:

Se il tuo compilatore supporta le espressioni fold , puoi usare template magic e std::index_sequencegenerare un elenco di inizializzatori con il valore che desideri. E puoi persino constexprfarlo e sentirti un capo:

#include <array>

/// [3]
/// This functions's only purpose is to ignore the index given as the second
/// template argument and to always produce the value passed in.
template<class T, size_t /*ignored*/>
constexpr T identity_func(const T& value) {
    return value;
}

/// [2]
/// At this point, we have a list of indices that we can unfold
/// into an initializer list using the `identity_func` above.
template<class T, size_t... Indices>
constexpr std::array<T, sizeof...(Indices)>
make_array_of_impl(const T& value, std::index_sequence<Indices...>) {
    return {identity_func<T, Indices>(value)...};
}

/// [1]
/// This is the user-facing function.
/// The template arguments are swapped compared to the order used
/// for std::array, this way we can let the compiler infer the type
/// from the given value but still define it explicitly if we want to.
template<size_t Size, class T>
constexpr std::array<T, Size> 
make_array_of(const T& value) {
    using Indices = std::make_index_sequence<Size>;
    return make_array_of_impl(value, Indices{});
}

// std::array<int, 4>{42, 42, 42, 42}
constexpr auto test_array = make_array_of<4/*, int*/>(42);
static_assert(test_array[0] == 42);
static_assert(test_array[1] == 42);
static_assert(test_array[2] == 42);
static_assert(test_array[3] == 42);
// static_assert(test_array[4] == 42); out of bounds

Puoi dare un'occhiata al codice al lavoro (su Wandbox)


-1

Non vedo alcun requisito nella domanda, quindi la soluzione deve essere generica: inizializzazione di un array multidimensionale possibilmente non specificato costruito da elementi di struttura possibilmente non specificati con un valore membro iniziale:

#include <string.h> 

void array_init( void *start, size_t element_size, size_t elements, void *initval ){
  memcpy(        start,              initval, element_size              );
  memcpy( (char*)start+element_size, start,   element_size*(elements-1) );
}

// testing
#include <stdio.h> 

struct s {
  int a;
  char b;
} array[2][3], init;

int main(){
  init = (struct s){.a = 3, .b = 'x'};
  array_init( array, sizeof(array[0][0]), 2*3, &init );

  for( int i=0; i<2; i++ )
    for( int j=0; j<3; j++ )
      printf("array[%i][%i].a = %i .b = '%c'\n",i,j,array[i][j].a,array[i][j].b);
}

Risultato:

array[0][0].a = 3 .b = 'x'
array[0][1].a = 3 .b = 'x'
array[0][2].a = 3 .b = 'x'
array[1][0].a = 3 .b = 'x'
array[1][1].a = 3 .b = 'x'
array[1][2].a = 3 .b = 'x'

EDIT: start+element_sizemodificato in(char*)start+element_size


1
Sono dubbioso se questa sia una soluzione o meno. Non sono sicuro che sizeof(void)sia valido.
Chris Lutz,

3
Non funziona Vengono inizializzati solo i primi due, i restanti non sono inizializzati. Sto usando GCC 4.0 su Mac OS X 10.4.
dreamlax,

Ciò invoca un comportamento indefinito perché i dati di origine nel secondo si memcpy()sovrappongono allo spazio di destinazione. Con un'implementazione ingenua di memcpy(), potrebbe funzionare ma non è necessario che il sistema lo faccia funzionare.
Jonathan Leffler,

-1

In passato (e non sto dicendo che sia una buona idea), avremmo impostato il primo elemento e poi:

memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);

Non sono nemmeno sicuro che funzionerebbe più (ciò dipenderebbe dall'implementazione di memcpy) ma funziona copiando ripetutamente l'elemento iniziale nel successivo - funziona anche per array di strutture.


Non funzionerà in modo affidabile. IMHO, lo standard avrebbe dovuto fornire funzioni simili memcpyma specificate l'ordine di copia bottom-up o top-down in caso di sovrapposizione, ma non è così.
supercat

Come ho detto, era solo qualcosa che facevamo che non funzionava in modo affidabile ma, all'epoca, eravamo più concentrati sull'efficienza che sull'evitare funzionalità prive di documenti. Mentre è più efficiente copiare la memoria in avanti, non c'è nulla nelle specifiche per dire che non può copiarla all'indietro, in un ordine casuale o dividerlo su più thread. memmove () offre la possibilità di copiare senza scontri.
Mike

Ciò equivale al codice in un'altra risposta - e imperfetto. L'uso memmove()non lo fa funzionare.
Jonathan Leffler,

-2

Se intendi in parallelo, penso che l'operatore virgola quando usato in combinazione con un'espressione possa farlo:

a[1]=1, a[2]=2, ..., a[indexSize]; 

o se intendi in un singolo costrutto, potresti farlo in un ciclo for:

for(int index = 0, value = 10; index < sizeof(array)/sizeof(array[0]); index++, value--)
  array[index] = index;

// Nota che l'operatore virgola in un elenco di argomenti non è l'operatore parallelo sopra descritto;

È possibile inizializzare una declerazione di array:

array[] = {1, 2, 3, 4, 5};

È possibile effettuare una chiamata a malloc / calloc / sbrk / alloca / etc per allocare una regione fissa di memoria a un oggetto:

int *array = malloc(sizeof(int)*numberOfListElements/Indexes);

e accedi ai membri tramite:

*(array + index)

Eccetera.


L'operatore virgola garantisce nominalmente la valutazione da sinistra a destra. Se non ci sono effetti collaterali nelle espressioni, allora potrebbe essere possibile parallelizzare le operazioni, ma sarebbe insolito per un compilatore farlo.
Jonathan Leffler,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.