Como inicializar todos os membros de uma matriz com o mesmo valor?

Eu tenho uma grande matriz em C (não C + + se isso faz diferença). Eu quero inicializar todos os membros para o mesmo valor. Eu poderia jurar que uma vez conheci uma maneira simples de fazer isso. Eu poderia usar memset() no meu caso, mas não há uma maneira de fazer isso que está embutido na syntax C?

A menos que esse valor seja 0 (caso em que você pode omitir alguma parte do inicializador e os elementos correspondentes serão inicializados como 0), não há um caminho fácil.

Não ignore a solução óbvia, no entanto:

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

Elementos com valores ausentes serão inicializados como 0:

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

Então isso irá inicializar todos os elementos para 0:

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

Em C ++, uma lista de boot vazia também inicializará todos os elementos para 0. Isso não é permitido com C:

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

Lembre-se de que objects com duração de armazenamento estático serão inicializados em 0 se nenhum inicializador for especificado:

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

E que “0” não significa necessariamente “all-bits-zero”, então usar o acima é melhor e mais portátil que memset (). (Valores de ponto flutuante serão inicializados para +0, pointers para valor nulo, etc.)

Se o seu compilador é o GCC, você pode usar a seguinte syntax:

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

Confira a descrição detalhada: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html

Para inicializar estaticamente uma matriz grande com o mesmo valor, sem vários copiar e colar, você pode usar macros:

 #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 você precisar alterar o valor, terá que fazer a substituição em apenas um lugar.

Edit: possíveis extensões úteis

(cortesia de Jonathan Leffler )

Você pode facilmente generalizar isso com:

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

Uma variante pode ser criada usando:

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

que trabalha com estruturas ou matrizes compostas.

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

nomes de macro são negociáveis.

Se você quiser garantir que todos os membros da matriz sejam inicializados explicitamente, apenas omita a dimensão da declaração:

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

O compilador deduzirá a dimensão da lista de inicializadores. Infelizmente, para matrizes multidimensionais, apenas a dimensão mais externa pode ser omitida:

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

está bem, mas

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

não é.

Eu vi um código que usava essa syntax:

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

Onde se torna particularmente útil é se você está fazendo uma matriz que usa enums como o índice:

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

Isso mantém as coisas em ordem, mesmo que você escreva alguns dos valores de enum fora de ordem.

Mais sobre esta técnica pode ser encontrada aqui e aqui .

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

Eu acho que isso é melhor que

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

incase o tamanho das mudanças da matriz.

Você pode fazer toda a coisa do inicializador estático como detalhado acima, mas pode ser uma chatice real quando o tamanho da sua matriz muda (quando a sua matriz é incorporada, se você não adicionar os inicializadores extras apropriados, você recebe lixo).

O memset dá a você um tempo de execução para fazer o trabalho, mas nenhum hit de código feito corretamente é imune a mudanças no tamanho do array. Eu usaria essa solução em quase todos os casos quando a matriz era maior do que, digamos, algumas dezenas de elementos.

Se fosse realmente importante que a matriz fosse declarada estaticamente, eu escreveria um programa para escrever o programa para mim e torná-lo parte do processo de criação.

Aqui está outro jeito:

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

Vejo:

Extensões C

Inits designados

Então faça a pergunta: Quando alguém pode usar extensões C?

O exemplo de código acima está em um sistema embarcado e nunca verá a luz de outro compilador.

Para inicializar tipos de dados ‘normais’ (como matrizes int), você pode usar a notação de colchetes, mas zerará os valores após o último caso ainda haja espaço na matriz:

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

Uma resposta levemente irônica; escreva a declaração

 array = initial_value 

na sua linguagem favorita com capacidade de matriz (a minha é Fortran, mas há muitas outras) e vinculá-la ao seu código C. Você provavelmente gostaria de envolvê-lo para ser uma function externa.

Se a matriz for int ou qualquer coisa com o tamanho de int ou o tamanho de seu padrão mem se ajustar a tempos exatos em um int (ou seja, todos os zeros ou 0xA5A5A5A5), a melhor maneira é usar memset () .

Caso contrário, chame memcpy () em um loop movendo o índice.

Existe uma maneira rápida de inicializar o array de qualquer tipo com um determinado valor. Funciona muito bem com grandes matrizes. Algoritmo é o seguinte:

  • inicializar o primeiro elemento da matriz (maneira usual)
  • copia parte que foi definida em parte que não foi definida, dobrando o tamanho a cada próxima operação de cópia

Para 1 000 000 elementos int array, é 4 vezes mais rápido que a boot normal de loop (i5, 2 núcleos, 2,3 GHz, 4GiB de memory, 64 bits):

loop runtime 0.004248 [seconds]

memfill() runtime 0.001085 [seconds]


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

Ninguém mencionou a ordem do índice para acessar os elementos da matriz inicializada. Meu código de exemplo dará um exemplo ilustrativo para ele.

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

A saída é:

 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 

Você pode usar a function memset.

 void *memset(void *array, int value, unsigned sizeofarray); 
  1. Se sua matriz for declarada como estática ou global, todos os elementos da matriz já terão o valor padrão 0.
  2. Alguns compiladores definem o array como 0 no modo de debugging.
  3. É fácil definir o padrão como 0: int array [10] = {0};
  4. No entanto, para outros valores, você usa memset () ou loop;

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

Cortando todas as conversas, a resposta curta é que, se você ativar a otimização em tempo de compilation, não fará nada melhor do que isso:

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

Bônus adicionado: o código é realmente legível 🙂

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

Ele vai dar oo / 5 5 5 5 5 5 ...... até o tamanho de toda matriz

Sei que o usuário Tarski respondeu a essa pergunta de maneira semelhante, mas acrescentei mais alguns detalhes. Perdoe alguns dos meus C porque estou um pouco enferrujado, já que estou mais inclinado a querer usar C ++, mas aqui vai.


Se você sabe o tamanho da matriz antes do tempo …

 #include  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" ); } 

Há algumas advertências acima; uma é que UINT myArray[size]; não é inicializado diretamente após a declaração, no entanto, o próximo bloco de código ou chamada de function inicializa cada elemento da matriz com o mesmo valor desejado. A outra ressalva é que você teria que escrever uma initializing function para cada type você suportaria e você também teria que modificar a function printArray() para suportar esses tipos.


Você pode experimentar este código com um complier on-line encontrado aqui .

Não vejo nenhum requisito na pergunta, portanto, a solução deve ser genérica: boot de uma matriz possivelmente não multidimensional não especificada criada a partir de elementos de estrutura possivelmente não especificados com um valor de membro inicial:

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

Resultado:

 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_size alterado para (char*)start+element_size