Eu tenho uma grande matriz em C (não C ++, se isso faz a diferença). Eu quero inicializar todos os membros do mesmo valor.
Eu poderia jurar que uma vez soube uma maneira simples de fazer isso. Eu poderia usar memset()
no meu caso, mas não existe uma maneira de fazer isso incorporada diretamente à sintaxe C?
enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };
estruct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };
. Se você remover as reticências…
, esses fragmentos serão compilados em C99 ou C11.memset()
discussão específica: stackoverflow.com/questions/7202411/... Eu acho que ele só funciona para 0.Respostas:
A menos que esse valor seja 0 (nesse caso, você pode omitir parte do inicializador e os elementos correspondentes serão inicializados como 0), não há uma maneira fácil.
Não negligencie a solução óbvia:
Os elementos com valores ausentes serão inicializados em 0:
Portanto, isso inicializará todos os elementos para 0:
No C ++, uma lista de inicialização vazia também inicializará todos os elementos para 0. Isso não é permitido com C:
Lembre-se de que objetos com duração de armazenamento estático serão inicializados como 0 se nenhum inicializador for especificado:
E que "0" não significa necessariamente "todos os bits-zero", portanto, usar o acima é melhor e mais portátil que memset (). (Os valores de ponto flutuante serão inicializados em +0, ponteiros para valor nulo etc.)
fonte
Se o seu compilador for o GCC, você poderá usar a seguinte sintaxe:
Confira a descrição detalhada: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
fonte
int
s aos dados estáticos, que são 256 K - exatamente o aumento de tamanho que você observou.int
s,int foo1 = 1, foo2 = 1, ..., foo65536 =1;
terá o mesmo aumento de tamanho.bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}
, embora eu não esteja certo de que seja mais legível que o formulário completo.Para inicializar estaticamente uma grande matriz com o mesmo valor, sem várias copiar e colar, você pode usar macros:
Se você precisar alterar o valor, precisará fazer a substituição em apenas um local.
Editar: possíveis extensões úteis
(cortesia de Jonathan Leffler )
Você pode generalizar isso facilmente com:
Uma variante pode ser criada usando:
que trabalha com estruturas ou matrizes compostas.
nomes de macro são negociáveis.
fonte
VAL_1X
não for um único inteiro, mas uma lista. Como estados Amigable, este também é o caminho a seguir para sistemas incorporados nos quais você deseja definir os valores init de uma memória EEPROM ou Flash. Nos dois casos, você não pode usarmemset()
.Se você deseja garantir que todos os membros da matriz sejam explicitamente inicializados, apenas omita a dimensão da declaração:
O compilador deduzirá a dimensão da lista de inicializadores. Infelizmente, para matrizes multidimensionais, apenas a dimensão mais externa pode ser omitida:
está bem, mas
não é.
fonte
int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Eu vi algum código que usava esta sintaxe:
Onde isso se torna particularmente útil é se você estiver criando uma matriz que usa enumerações como índice:
Isso mantém as coisas em ordem, mesmo que você escreva alguns valores enum fora de ordem.
Mais sobre esta técnica pode ser encontrada aqui e aqui .
fonte
char const *array[] = { ... };
ou até mesmochar const * const array[] = { ... };
, não é?Eu acho que isso é melhor do que
caso o tamanho da matriz seja alterado.
fonte
memset(myArray, VALUE, ARRAY_SIZE);
Você pode fazer toda a coisa do inicializador estático, conforme detalhado acima, mas pode ser uma chatice quando o tamanho da sua matriz muda (quando sua matriz embiggens, se você não adicionar os inicializadores extras apropriados, obterá lixo).
O memset fornece um hit de tempo de execução para o trabalho, mas nenhum hit de tamanho de código feito corretamente é imune a alterações no tamanho da matriz. Eu usaria essa solução em quase todos os casos em que 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 fazer parte do processo de compilação.
fonte
memset
para inicializar a matriz?Aqui está outra maneira:
Vejo:
Extensões C
Unidades designadas
Em seguida, faça a pergunta: quando alguém pode usar extensões C?
O exemplo de código acima está em um sistema incorporado e nunca verá a luz de outro compilador.
fonte
Para inicializar tipos de dados 'normais' (como matrizes int), você pode usar a notação de colchete, mas zerará os valores após o último se ainda houver espaço na matriz:
fonte
Se a matriz for int ou qualquer coisa com o tamanho de int ou o tamanho do seu padrão de mem se encaixar vezes exatas em um int (ou seja, todos os zeros ou 0xA5A5A5A5), a melhor maneira é usar memset () .
Caso contrário, chame memcpy () em um loop para mover o índice.
fonte
Uma resposta levemente explícita; escreva a declaração
na sua linguagem favorita de capacidade de array (a minha é Fortran, mas existem muitas outras) e vincule-a ao seu código C. Você provavelmente desejaria agrupá-lo para ser uma função externa.
fonte
Existe uma maneira rápida de inicializar uma matriz de qualquer tipo com determinado valor. Funciona muito bem com matrizes grandes. O algoritmo é o seguinte:
Para a matriz de
1 000 000
elementosint
, é 4 vezes mais rápido que a inicialização normal do loop (i5, 2 núcleos, 2,3 GHz, memória 4GiB, 64 bits):loop runtime 0.004248 [seconds]
memfill() runtime 0.001085 [seconds]
fonte
memfill()
código leva cerca de 1200 µs. No entanto, nas iterações subsequentes, o loop leva cerca de 900-1000 µs enquanto omemfill()
código leva 1000-1300 µs. A primeira iteração provavelmente é afetada pelo tempo para preencher o cache. Inverta os testes ememfill()
é lento pela primeira vez.Ninguém mencionou a ordem do índice para acessar os elementos da matriz inicializada. Meu código de exemplo fornecerá um exemplo ilustrativo.
A saída é:
fonte
<iostream>
não é válido ,C
poisstd::cout
,std::cin
etc faz parte dostd::namespace
eC
não é compatívelnamespaces
. Tente usar<stdio.h>
para emprintf(...)
vez disso.Cortando toda a conversa, a resposta curta é que, se você ativar a otimização em tempo de compilação, não fará melhor que isso:
Bônus adicionado: o código é realmente legível :)
fonte
exemplo: matriz int [10]; memset (matriz, -1, 10 * sizeof (int));
fonte
Ele dará o / p 5 5 5 5 5 5 ...... até o tamanho de toda a matriz
fonte
Sei que o usuário
Tarski
respondeu a essa pergunta de maneira semelhante, mas adicionei mais alguns detalhes. Perdoe parte do meu C porque estou um pouco enferrujado, pois estou mais inclinado a querer usar o C ++, mas aqui está.Se você souber o tamanho da matriz antes do tempo ...
Existem algumas ressalvas acima; uma é que
UINT myArray[size];
não é inicializada diretamente na declaração; no entanto, o próximo bloco de código ou chamada de função inicializa cada elemento da matriz com o mesmo valor desejado. A outra ressalva é que você teria que escrever uminitializing function
para cada um dos quaistype
você apoiará e também teria que modificar aprintArray()
função para suportar esses tipos.Você pode tentar esse código com um complier online encontrado aqui .
fonte
Para inicialização atrasada (isto é, inicialização do construtor do membro da classe), considere:
fonte
Eu sei que a pergunta original menciona explicitamente C e não C ++, mas se você (como eu) veio aqui procurando uma solução para matrizes C ++, aqui está um truque:
Se o seu compilador suportar expressões de dobra , você poderá usar a mágica do modelo e
std::index_sequence
gerar uma lista de inicializadores com o valor desejado. E você pode equilibrarconstexpr
e se sentir como um chefe:Você pode dar uma olhada no código no trabalho (na Wandbox)
fonte
Não vejo requisitos na pergunta, portanto a solução deve ser genérica: inicialização de uma matriz multidimensional possivelmente não especificada, construída a partir de elementos de estrutura não especificados com um valor inicial de membro:
Resultado:
EDIT:
start+element_size
alterado para(char*)start+element_size
fonte
sizeof(void)
é válido.memcpy()
sobrepõem ao espaço de destino. Com uma implementação ingênua dememcpy()
, pode funcionar, mas não é necessário que o sistema o faça funcionar.De volta ao dia (e não estou dizendo que é uma boa ideia), definiríamos o primeiro elemento e depois:
memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);
Nem tenho certeza de que funcionaria mais (isso dependeria da implementação do memcpy), mas funciona copiando repetidamente o elemento inicial para o próximo - até funciona para matrizes de estruturas.
fonte
memcpy
mas especificadas de baixo para cima ou de cima para baixo em caso de sobreposição, mas não.memmove()
não o faz funcionar.Se você quer dizer em paralelo, acho que o operador de vírgula quando usado em conjunto com uma expressão pode fazer isso:
ou se você quer dizer em uma única construção, você pode fazer isso em um loop for:
// Observe que o operador de vírgula em uma lista de argumentos não é o operador paralelo descrito acima;
Você pode inicializar uma decleração de matriz:
Você pode fazer uma chamada para malloc / calloc / sbrk / alloca / etc para alocar uma região fixa de armazenamento para um objeto:
e acesse os membros por:
Etc.
fonte