在 C 中制作二维数组的最佳方法是什么
What is the best way to make 2 dimensional array in C
我想在 C 中创建一个二维数组。
我知道 1 种方法。
#include <stdlib.h>
void my_func(int **arr)
{
printf("test2: %d\n", arr[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int **arr = (int **)malloc(sizeof(int *) * 3);
arr[0] = (int *)malloc(sizeof(int) * 4);
arr[1] = (int *)malloc(sizeof(int) * 4);
arr[2] = (int *)malloc(sizeof(int) * 4);
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[0][3] = 4;
arr[1][0] = 3;
arr[1][1] = 4;
arr[1][2] = 5;
arr[1][3] = 6;
arr[2][0] = 5;
arr[2][1] = 6;
arr[2][2] = 7;
arr[2][3] = 8;
printf("test1: %d\n", arr[0][1]);
my_func(arr);
}
在这种情况下,数组可以很好地作为参数传递给函数。
但它不是那么漂亮。
如果数组有很多值(例如 20*20),我需要逐行输入每个值。
所以我搜索了一下,找到了一种方法来制作这样的数组。
#include <stdio.h>
void my_func(int **arr)
{
printf("test2: %d", arr[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
printf("test1: %d", arr[0][1]);
my_func(arr);
}
简洁明了,不会累死我。
但是当数组传递给函数时出了点问题。
而且编译的时候有如下警告
test_2D_array.c:20:11: warning: incompatible pointer types passing 'int [3][4]' to
parameter of type 'int **' [-Wincompatible-pointer-types]
my_func(arr);
^~~
test_2D_array.c:3:20: note: passing argument to parameter 'arr' here
void my_func(int **arr)
^
1 warning generated.
甚至函数也无法访问数组参数。存在分段错误。
所以我想知道制作数组的最佳方法,它可以作为参数传递给任何函数,并且比我的第一个代码更简单。
感谢您的阅读。
函数可以声明为
void my_func(int arr[][4])
{
printf("test2: %d", arr[0][1]);
}
请注意,您不必指定第一个维度的大小。
这个
int **arr = (int **)malloc(sizeof(int *) * 3);
不是二维数组的声明或分配
这里创建了一个元素类型为int *
的一维数组。然后一维数组的每个元素依次指向一个分配的元素类型为int
.
的一维数组
二维数组的声明
const int row = 3;
const int col = 4;
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
不正确。可变长度数组(并且您声明了可变长度数组)可能未在声明中初始化。
你可以改写
enum { row = 3, col = 4 };
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
当这样的数组被传递给一个函数时,它被隐式转换为指向其类型 int ( * )[col]
.
的第一个元素的指针
您可以通过以下方式将其传递给具有可变长度数组类型参数的函数
void my_func( size_t row, size_t col, int arr[row][col] )
{
printf("test2: %d", arr[0][1]);
}
或者如果将枚举的定义放在函数声明之前
enum { row = 3, col = 4 };
那么函数也可以这样声明
void my_func( int arr[][col], size_t row )
{
printf("test2: %d", arr[0][1]);
}
这是一个展示三种不同方法的演示程序。第一个数组是用数组大小的编译时常量定义的。创建可变长度数组时的第二个。第三个是动态分配指向一维数组指针的一维数组。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { row = 3, col = 4 };
void output1( int a[][col], size_t row )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
void output2( size_t row, size_t col, int a[row][col] )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
void output3( int **a, size_t row, size_t col )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
int main(void)
{
int arr1[row][col] =
{
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
output1( arr1, row );
putchar( '\n' );
const size_t row = 3, col = 4;
int arr2[row][col];
memcpy( arr2, arr1, row * col * sizeof( int ) );
output2( row, col, arr2 );
putchar( '\n' );
int **arr3 = malloc( row * sizeof( int * ) );
for ( size_t i = 0; i < row; i++ )
{
arr3[i] = malloc( col * sizeof( int ) );
memcpy( arr3[i], arr1[i], col * sizeof( int ) );
}
output3( arr3, row, col );
putchar( '\n' );
for ( size_t i = 0; i < row; i++ )
{
free( arr3[i] );
}
free( arr3 );
}
程序输出为
1 2 3 4
3 4 5 6
5 6 7 8
1 2 3 4
3 4 5 6
5 6 7 8
1 2 3 4
3 4 5 6
5 6 7 8
注意函数 output2
可以与数组 arr1
一起使用,就像它与数组 arr2
.
一起使用一样
它需要一个看起来很有趣的类型转换,但我是这样做的:
#include <stdio.h>
void my_func(int **arr, int cols)
{
int (*matrix)[cols] = arr;
printf("test2: %d\n", matrix[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int arr[3][4] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
printf("test1: %d\n", arr[0][1]);
my_func(arr, col);
}
IDEOne Link
假设没有动态分配
1 #include <stdio.h>
1
2 void func(int *arr, int row, int col) {
3 int i, j;
4
5 for (i = 0; i < row * col; i++) {
6 if (i && (i % col == 0))
7 printf("\n");
8 printf("%d ", arr[i]);
9 }
10
11 printf("\n");
12 }
13
14 int main(int argc, char *argv[]) {
15 // can be this
16 int arr1[] = {
17 1,2,3, // row 0
18 4,5,6 // row 1
19 };
20
21 // or this way
22 int arr2[2][3] = {
23 {0,1,2}, // row 0
24 {4,5,6} // row 1
25 };
26
27 func(arr1, 2, 3);
28 func((int*)arr2, 2, 3);
29 return 0;
30 }
~
首先,您不能初始化可变大小的二维数组,如 'Vlad from Moscow' 在他的回答中提到的那样。
相反,您只需指定第二个维度的大小,将第一个维度留空。
其次,您的 my_func(int **arr)
期望 pointer to pointer to int
而您只是传递数组的地址,这就是编译器抛出不兼容错误的原因。
您的固定代码将如下所示:
#include <stdio.h>
void my_func(int **arr)
{
printf("test2: %d", arr[0][1]);
}
int main(void)
{
int arr[][4] = {1,2,3,4,
3,4,5,6,
5,6,7,8};
int *p = (int *)arr;
int **p1 = &p;
printf("test1: %d", arr[0][1]);
my_func(p1);
}
现在 const int row = 3
和 const int column = 4
没有用了,所以您可以删除它们。
我想在 C 中创建一个二维数组。
我知道 1 种方法。
#include <stdlib.h>
void my_func(int **arr)
{
printf("test2: %d\n", arr[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int **arr = (int **)malloc(sizeof(int *) * 3);
arr[0] = (int *)malloc(sizeof(int) * 4);
arr[1] = (int *)malloc(sizeof(int) * 4);
arr[2] = (int *)malloc(sizeof(int) * 4);
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[0][3] = 4;
arr[1][0] = 3;
arr[1][1] = 4;
arr[1][2] = 5;
arr[1][3] = 6;
arr[2][0] = 5;
arr[2][1] = 6;
arr[2][2] = 7;
arr[2][3] = 8;
printf("test1: %d\n", arr[0][1]);
my_func(arr);
}
在这种情况下,数组可以很好地作为参数传递给函数。 但它不是那么漂亮。 如果数组有很多值(例如 20*20),我需要逐行输入每个值。
所以我搜索了一下,找到了一种方法来制作这样的数组。
#include <stdio.h>
void my_func(int **arr)
{
printf("test2: %d", arr[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
printf("test1: %d", arr[0][1]);
my_func(arr);
}
简洁明了,不会累死我。 但是当数组传递给函数时出了点问题。 而且编译的时候有如下警告
test_2D_array.c:20:11: warning: incompatible pointer types passing 'int [3][4]' to
parameter of type 'int **' [-Wincompatible-pointer-types]
my_func(arr);
^~~
test_2D_array.c:3:20: note: passing argument to parameter 'arr' here
void my_func(int **arr)
^
1 warning generated.
甚至函数也无法访问数组参数。存在分段错误。
所以我想知道制作数组的最佳方法,它可以作为参数传递给任何函数,并且比我的第一个代码更简单。
感谢您的阅读。
函数可以声明为
void my_func(int arr[][4])
{
printf("test2: %d", arr[0][1]);
}
请注意,您不必指定第一个维度的大小。
这个
int **arr = (int **)malloc(sizeof(int *) * 3);
不是二维数组的声明或分配
这里创建了一个元素类型为int *
的一维数组。然后一维数组的每个元素依次指向一个分配的元素类型为int
.
二维数组的声明
const int row = 3;
const int col = 4;
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
不正确。可变长度数组(并且您声明了可变长度数组)可能未在声明中初始化。
你可以改写
enum { row = 3, col = 4 };
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
当这样的数组被传递给一个函数时,它被隐式转换为指向其类型 int ( * )[col]
.
您可以通过以下方式将其传递给具有可变长度数组类型参数的函数
void my_func( size_t row, size_t col, int arr[row][col] )
{
printf("test2: %d", arr[0][1]);
}
或者如果将枚举的定义放在函数声明之前
enum { row = 3, col = 4 };
那么函数也可以这样声明
void my_func( int arr[][col], size_t row )
{
printf("test2: %d", arr[0][1]);
}
这是一个展示三种不同方法的演示程序。第一个数组是用数组大小的编译时常量定义的。创建可变长度数组时的第二个。第三个是动态分配指向一维数组指针的一维数组。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { row = 3, col = 4 };
void output1( int a[][col], size_t row )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
void output2( size_t row, size_t col, int a[row][col] )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
void output3( int **a, size_t row, size_t col )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
int main(void)
{
int arr1[row][col] =
{
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
output1( arr1, row );
putchar( '\n' );
const size_t row = 3, col = 4;
int arr2[row][col];
memcpy( arr2, arr1, row * col * sizeof( int ) );
output2( row, col, arr2 );
putchar( '\n' );
int **arr3 = malloc( row * sizeof( int * ) );
for ( size_t i = 0; i < row; i++ )
{
arr3[i] = malloc( col * sizeof( int ) );
memcpy( arr3[i], arr1[i], col * sizeof( int ) );
}
output3( arr3, row, col );
putchar( '\n' );
for ( size_t i = 0; i < row; i++ )
{
free( arr3[i] );
}
free( arr3 );
}
程序输出为
1 2 3 4
3 4 5 6
5 6 7 8
1 2 3 4
3 4 5 6
5 6 7 8
1 2 3 4
3 4 5 6
5 6 7 8
注意函数 output2
可以与数组 arr1
一起使用,就像它与数组 arr2
.
它需要一个看起来很有趣的类型转换,但我是这样做的:
#include <stdio.h>
void my_func(int **arr, int cols)
{
int (*matrix)[cols] = arr;
printf("test2: %d\n", matrix[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int arr[3][4] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
printf("test1: %d\n", arr[0][1]);
my_func(arr, col);
}
IDEOne Link
假设没有动态分配
1 #include <stdio.h>
1
2 void func(int *arr, int row, int col) {
3 int i, j;
4
5 for (i = 0; i < row * col; i++) {
6 if (i && (i % col == 0))
7 printf("\n");
8 printf("%d ", arr[i]);
9 }
10
11 printf("\n");
12 }
13
14 int main(int argc, char *argv[]) {
15 // can be this
16 int arr1[] = {
17 1,2,3, // row 0
18 4,5,6 // row 1
19 };
20
21 // or this way
22 int arr2[2][3] = {
23 {0,1,2}, // row 0
24 {4,5,6} // row 1
25 };
26
27 func(arr1, 2, 3);
28 func((int*)arr2, 2, 3);
29 return 0;
30 }
~
首先,您不能初始化可变大小的二维数组,如 'Vlad from Moscow' 在他的回答中提到的那样。
相反,您只需指定第二个维度的大小,将第一个维度留空。
其次,您的 my_func(int **arr)
期望 pointer to pointer to int
而您只是传递数组的地址,这就是编译器抛出不兼容错误的原因。
您的固定代码将如下所示:
#include <stdio.h>
void my_func(int **arr)
{
printf("test2: %d", arr[0][1]);
}
int main(void)
{
int arr[][4] = {1,2,3,4,
3,4,5,6,
5,6,7,8};
int *p = (int *)arr;
int **p1 = &p;
printf("test1: %d", arr[0][1]);
my_func(p1);
}
现在 const int row = 3
和 const int column = 4
没有用了,所以您可以删除它们。