Quero zerar repetidamente um grande array 2d em C. Isto é o que faço no momento:
// Array of size n * m, where n may not equal m
for(j = 0; j < n; j++)
{
for(i = 0; i < m; i++)
{
array[i][j] = 0;
}
}
Tentei usar o memset:
memset(array, 0, sizeof(array))
Mas isso só funciona para arrays 1D. Quando imprimo o conteúdo da matriz 2D, a primeira linha é zeros, mas depois recebo uma carga de números grandes aleatórios e ela trava.
memset
, porque você mencionou travar por zerar apenas uma linha também.int d0=10, d1=20; int arr[d0][d1]
ememset(arr, 0, sizeof arr);
funcionou como esperado (gcc 3.4.6, compilado com-std=c99 -Wall
sinalizadores). Eu percebo que "funciona na minha máquina" significa agachamento diddly, masmemset(arr, 0, sizeof arr);
deveria ter funcionado.sizeof arr
deve retornar o número de bytes usados por toda a matriz (d0 * d1 * sizeof (int)).sizeof array[0] * m * n
não fornecerá o tamanho correto da matriz.int array[][10]
, então,sizeof(array) == sizeof(int*)
o tamanho da primeira dimensão não é conhecido. O OP não especificou como o array foi obtido.Se
array
for realmente uma matriz, você pode "zerá-la" com:Mas há dois pontos que você deve saber:
array
for realmente um "array two-d", ou seja, foi declaradoT array[M][N];
para algum tipoT
.array
foi declarado. Se você passá-lo para uma função, o nomearray
decairá para um ponteiro esizeof
não fornecerá o tamanho do array.Vamos fazer um experimento:
Na minha máquina, as impressões acima:
Mesmo sendo
arr
um array, ele decai para um ponteiro para seu primeiro elemento quando passado paraf()
e, portanto, os tamanhos impressosf()
são "errados". Além disso,f()
o tamanho dearr[0]
é o tamanho da matrizarr[0]
, que é uma "matriz [5] deint
". Não é o tamanho de umint *
, porque o "decaimento" só acontece no primeiro nível, e é por isso que precisamos declararf()
como levando um ponteiro para um array de tamanho correto.Portanto, como eu disse, o que você estava fazendo originalmente só funcionará se as duas condições acima forem satisfeitas. Caso contrário, você precisará fazer o que outros disseram:
Finalmente,
memset()
e ofor
loop que você postou não são equivalentes no sentido estrito. Pode haver (e tem havido) compiladores onde "todos os bits zero" não são iguais a zero para certos tipos, como ponteiros e valores de ponto flutuante. Duvido que você precise se preocupar com isso.fonte
memset(array, 0, n*n*sizeof array[0][0]);
Eu acho que você quer dizerm*n
não están*n
certo?memset
funciona no nível de byte (char). Como1
ou2
não tem os mesmos bytes na representação subjacente, você não pode fazer isso commemset
.int
no seu sistema há 4 bytes" em algum lugar antes do exemplo de trabalho mínimo, para que o leitor possa calcular facilmente as somas.Bem, a maneira mais rápida de fazer isso é não fazer nada.
Parece estranho, eu sei, aqui está um pseudocódigo:
Na verdade, ele ainda está limpando o array, mas apenas quando algo está sendo gravado no array. Esta não é uma grande vantagem aqui. No entanto, se o array 2D foi implementado usando, digamos, uma árvore quádrupla (não dinâmica), ou uma coleção de linhas de dados, então você pode localizar o efeito do sinalizador booleano, mas você precisa de mais sinalizadores. Na árvore quádrupla basta definir o sinalizador vazio para o nó raiz, na matriz de linhas apenas definir o sinalizador para cada linha.
O que leva à pergunta "por que você deseja zerar repetidamente um grande array 2d"? Para que é usado o array? Existe uma maneira de alterar o código para que a matriz não precise ser zerada?
Por exemplo, se você tivesse:
ou seja, use-o para um buffer de acumulação, então alterá-lo assim melhoraria o desempenho sem fim:
Isso não exige que a matriz seja limpa, mas ainda funciona. E isso será muito mais rápido do que limpar a matriz. Como eu disse, a maneira mais rápida é não fazer isso em primeiro lugar.
fonte
Se você for realmente obcecado por velocidade (e não tanto por portabilidade), acho que a maneira mais rápida de fazer isso seria usar o vetor intrínseco SIMD. por exemplo, em CPUs Intel, você pode usar estas instruções SSE2:
Cada instrução de armazenamento definirá quatro ints de 32 bits para zero em um acerto.
p deve estar alinhado com 16 bytes, mas essa restrição também é boa para a velocidade porque ajudará o cache. A outra restrição é que p deve apontar para um tamanho de alocação que é um múltiplo de 16 bytes, mas isso também é legal porque nos permite desenrolar o loop facilmente.
Faça um loop e desenrole o loop algumas vezes, e você terá um inicializador muito rápido:
Há também uma variante
_mm_storeu
que ignora o cache (ou seja, zerar o array não polui o cache), o que pode fornecer alguns benefícios de desempenho secundários em algumas circunstâncias.Veja aqui a referência SSE2: http://msdn.microsoft.com/en-us/library/kcwz153a(v=vs.80).aspx
fonte
Se você inicializar a matriz com
malloc
, usecalloc
; ele irá zerar seu array gratuitamente. (Obviamente, o mesmo desempenho do memset, apenas menos código para você.)fonte
int array[N][M] = {0};
... pelo menos no GCC 4.8.
fonte
Como seu array 2D foi declarado?
Se for algo como:
Você pode zerá-lo fazendo:
fonte
memset(a, 0, sizeof(char)*10*10);
funciona bem para mim. , como isso acontece?Use calloc em vez de malloc. calloc iniciará todos os campos em 0.
int * a = (int *) calloc (n, tamanho de (int));
// todas as células de a foram inicializadas com 0
fonte
Acho que a maneira mais rápida de fazer isso manualmente é seguindo o código. Você pode comparar sua velocidade com a função memset, mas não deve ser mais lenta.
(mude o tipo dos ponteiros ptr e ptr1 se o seu tipo de array for diferente do int)
fonte
memset
para os tipos de caracteres.fonte
Você pode tentar isso
fonte
Isso acontece porque sizeof (array) fornece o tamanho de alocação do objeto apontado por array . ( array é apenas um ponteiro para a primeira linha de seu array multidimensional). No entanto, você alocou j arrays de tamanho i . Consequentemente, você precisa multiplicar o tamanho de uma linha, que é retornado por sizeof (array) com o número de linhas que você alocou, por exemplo:
Observe também que sizeof (array) só funcionará para arrays alocados estaticamente. Para uma matriz alocada dinamicamente, você escreveria
fonte
sizeof
operador,array
não é um ponteiro (se foi declarado um array). Veja minha resposta para um exemplo.