给二维数组赋值的最佳方法是什么?



我想知道给二维数组赋值的最优方法是什么

比如说,我想把值12赋值给下面的数组

for (int i = 0; i < m; i+++)
for (int j = 0; j < n; j++)
array[i][j] = 10

在没有for循环的情况下,是否有更好的方法来做到这一点?

您的代码很好,可读且简单,除了一些错别字。只要确保对ij使用与nm相同的类型即可。

#define N 10
#define M 10
int array[M][N];
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++)
array[i][j] = 0;
}

以这种方式编写代码的优点是它既适用于平面二维数组int array[M][N],也适用于数组的数组int *array[M]以及指向数组的数组的指针int **array

如果数组是平面二维整数数组,且值为0,则有另一种选择:

memset(array, 0, sizeof(array[0][0]) * M * N);

但是它只适用于非常特定的值,这些值在内存中的所有位置都用相同的字节表示。这就是0-1在常规双互补体系结构中的情况,以及其他254个不太明显的值(40亿)。

您也可以初始化单行并将其复制到下面的行…

这样的优化是令人困惑的,容易出错和不必要的,因为现代优化编译器会为此生成非常有效的代码:

#define M 10
#define N 10
void clear_matrix(int array[M][N]) {
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++)
array[i][j] = 0;
}
}

指出:

  • 代码正确性总是优于优化:快速获得不正确结果的目的是什么?
  • 在优化之前,始终要进行基准测试和配置,并首先关注作为明显目标的瓶颈。
  • 矩阵初始化不太可能成为瓶颈。如果是,你的算法可能有问题。
  • 找到一个更好的算法,降低复杂性,比微优化更有成效。

这个问题几乎无法回答。简单的测试:

#define ROWS 1000
#define COLS 4000
int arr[ROWS][COLS];
void __attribute__((noinline)) set(int val)
{
for(size_t col = 0; col < COLS; col++)
{
arr[0][col] = val;
}
for(size_t row = 1; row < ROWS; row++)
{
memcpy(arr[row], arr[0], sizeof(arr[0]));
}
}
void __attribute__((noinline)) set1(int val)
{
static int arr1[COLS];
for(size_t col = 0; col < COLS; col++)
{
arr1[col] = val;
}
for(size_t row = 0; row < ROWS; row++)
{
memcpy(arr[row], arr1, sizeof(arr1));
}
}

void __attribute__((noinline)) set2(int val)
{
for(size_t row = 0; row < ROWS; row++)
for(size_t col = 0; col < COLS; col++)
{
arr[row][col] = val;
}
}

int main(void)
{
clock_t begin, end;
double time_spent;
begin = clock();
for(int x = 0; x < 1000; x++)
{
set(x);
}
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("%fn", time_spent);
begin = clock();
for(int x = 0; x < 1000; x++)
{
set1(x);
}
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("%fn", time_spent);

begin = clock();
for(int x = 0; x < 1000; x++)
{
set2(x);
}
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("%fn", time_spent);
}

Godbolt表明循环方法是最快的:https://godbolt.org/z/K9Gcbs

1.162777
1.009047
0.973361

但是通过ubuntu 20.4 64位测试(相同的编译器版本,相同的编译器选项)给出了相反的结果。

0.542433
0.502667
0.936434

所以结论是:永远是基准。不要相信观点和神话。

相关内容