Самый быстрый способ обнулить 2-й массив в C?

Я хочу неоднократно обнулить большой 2-й массив в C. Это - то, что я делаю в данный момент:

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

Я попытался использовать memset:

memset(array, 0, sizeof(array))

Но это только работает на 1D массивы. Когда я, которого обнуляет printf, который содержание 2D массива, первая строка, но затем я получил загрузку случайных больших количеств и она отказывает.

88
задан Csaba Toth 19 July 2016 в 04:46
поделиться

8 ответов

memset(array, 0, sizeof(array[0][0]) * m * n);

Где m и n - ширина и высота двумерного массива (в вашем примере у вас квадратный двумерный массив, поэтому m == n).

169
ответ дан 24 November 2019 в 07:25
поделиться

Как был объявлен ваш 2D-массив?

Если это что-то вроде:

int arr[20][30];

Вы можете обнулить его, выполнив:

memset(arr, sizeof(int)*20*30);
2
ответ дан 24 November 2019 в 07:25
поделиться
memset(array, 0, sizeof(int [n][n]));
0
ответ дан 24 November 2019 в 07:25
поделиться

Ну, самый быстрый способ сделать это - вообще этого не делать.

Звучит странно, я знаю, вот какой-то псевдокод:

int array [][];
bool array_is_empty;


void ClearArray ()
{
   array_is_empty = true;
}

int ReadValue (int x, int y)
{
   return array_is_empty ? 0 : array [x][y];
}

void SetValue (int x, int y, int value)
{
   if (array_is_empty)
   {
      memset (array, 0, number of byte the array uses);
      array_is_empty = false;
   }
   array [x][y] = value;
}

На самом деле, он все еще очищает массив, но только когда что-то записывается в массив. В этом нет большого преимущества. Однако, если 2D-массив был реализован с использованием, скажем, дерева квадратов (не динамического разума) или набора строк данных, то вы можете локализовать эффект логического флага, но вам понадобится больше флагов. В дереве квадратов просто установите пустой флаг для корневого узла, в массиве строк просто установите флаг для каждой строки.

Это приводит к вопросу «почему вы хотите многократно обнулять большой двумерный массив»? Для чего используется массив? Есть ли способ изменить код, чтобы массив не нуждался в обнулении?

Например, если у вас есть:

clear array
for each set of data
  for each element in data set
    array += element 

то есть использовать его для буфера накопления, а затем изменить его таким образом, чтобы повысить производительность no end:

 for set 0 and set 1
   for each element in each set
     array = element1 + element2

 for remaining data sets
   for each element in data set
     array += element 

Это не требует очистки массива, но все равно работает. И это будет намного быстрее, чем очистка массива. Как я уже сказал, самый быстрый способ - это вообще не делать этого.

9
ответ дан 24 November 2019 в 07:25
поделиться

Это происходит потому, что sizeof (array) дает вам размер выделения для объекта, на который указывает array . ( array - это просто указатель на первую строку вашего многомерного массива). Однако вы выделили j массивов размером i . Следовательно, вам нужно умножить размер одной строки, возвращаемой функцией sizeof (array), на количество выделенных вами строк, например :

bzero(array, sizeof(array) * j);

. Также обратите внимание, что sizeof (array) будет работать только для статически выделенных массивов. Для динамически распределенного массива вы должны написать

size_t arrayByteSize = sizeof(int) * i * j; 
int *array = malloc(array2dByteSite);
bzero(array, arrayByteSize);
-2
ответ дан 24 November 2019 в 07:25
поделиться

Я думаю, что самый быстрый способ сделать это вручную - это выполнить код. Вы можете сравнить его скорость с функцией memset, но она не должна быть медленнее.

(изменить тип указателей ptr и ptr1, если тип вашего массива отличается от int)


#define SIZE_X 100
#define SIZE_Y 100

int *ptr, *ptr1;
ptr = &array[0][0];
ptr1 = ptr + SIZE_X*SIZE_Y*sizeof(array[0][0]);

 while (ptr 

0
ответ дан 24 November 2019 в 07:25
поделиться

Если array действительно массив, то вы можете "обнулить" его с помощью:

memset(array, 0, sizeof array);

Но есть два момента, которые вы должны знать:

  • это работает только если array действительно "двумерный массив", т.е., был объявлен T array[M][N]; для некоторого типа T.
  • он работает только в той области видимости, где был объявлен array. Если передать его в функцию, то имя array распадается на указатель, и sizeof не даст вам размер массива.

Давайте проведем эксперимент:

#include <stdio.h>

void f(int (*arr)[5])
{
    printf("f:    sizeof arr:       %zu\n", sizeof arr);
    printf("f:    sizeof arr[0]:    %zu\n", sizeof arr[0]);
    printf("f:    sizeof arr[0][0]: %zu\n", sizeof arr[0][0]);
}

int main(void)
{
    int arr[10][5];
    printf("main: sizeof arr:       %zu\n", sizeof arr);
    printf("main: sizeof arr[0]:    %zu\n", sizeof arr[0]);
    printf("main: sizeof arr[0][0]: %zu\n\n", sizeof arr[0][0]);
    f(arr);
    return 0;
}

На моей машине вышеприведенное выводит:

main: sizeof arr:       200
main: sizeof arr[0]:    20
main: sizeof arr[0][0]: 4

f:    sizeof arr:       8
f:    sizeof arr[0]:    20
f:    sizeof arr[0][0]: 4

Несмотря на то, что arr является массивом, при передаче в f() он распадается до указателя на первый элемент, и поэтому размеры, выводимые в f(), "неправильные". Также в f() размер arr[0] является размером массива arr[0], который представляет собой "массив [5] из int". Это не размер int *, потому что "распад" происходит только на первом уровне, и поэтому нам нужно объявить f() как принимающий указатель на массив правильного размера.

Итак, как я уже сказал, то, что вы делали изначально, будет работать, только если выполняются два вышеуказанных условия. Если нет, вам нужно будет сделать то, что сказали другие:

memset(array, 0, m*n*sizeof array[0][0]);

Наконец, memset() и for цикл, который вы опубликовали, не эквивалентны в строгом смысле. Могут существовать (и существовали) компиляторы, в которых "все биты нулевые" не равны нулю для определенных типов, таких как указатели и значения с плавающей точкой. Однако я сомневаюсь, что вам стоит беспокоиться об этом.

74
ответ дан 24 November 2019 в 07:25
поделиться

Если вы инициализируете массив с помощью malloc, используйте вместо этого calloc; это обнулит ваш массив бесплатно. (Совершенство очевидно такое же, как и у memset, просто меньше кода для вас)

.
5
ответ дан 24 November 2019 в 07:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: