동적으로 할당 된 2 차원 배열을 사용하려면 올바른 포인터 유형을 사용해야합니다. (int **)
은 서로 다른 할당을 가리키는 포인터 배열의 첫 번째 요소를 가리키는 포인터에 대한 포인터입니다. 이런 종류의 코드 결과는 들쭉날쭉 한 배열이지만 2 차원 배열은 아닙니다. 할당 된 메모리는 (배열 할당이 있어야합니다으로) 연속이 보장되지 않습니다
size_t num_rows = 3;
size_t num_cols = 5;
int **jagged_arr = malloc(sizeof *jagged_arr * num_rows);
for (size_t i = 0; i < num_rows; i++) {
jagged_arr[i] = malloc(sizeof *jagged_arr[i] * num_cols);
}
하나의 가능성은 단순히 1 차원 배열에 대한 스토리지를 할당하고, 2 차원 배열 인덱스에서이 배열에 오프셋을 계산하는 것입니다.이것은 잘 작동하지만, 그 결과는 2 차원 배열이 아닌 :
size_t num_elems = num_rows * num_cols;
int *simulated_2d_arr = malloc(sizeof *simulated_2d_arr * num_elems);
이 2 차원 배열로 인덱스 될 수 있지만, 1 차원 인덱스 열의 수와 2 차원 배열의 인덱스로부터 계산 될 수있다 :
for (size_t i = 0; i < num_rows; i++) {
for (size_t j = 0; j < num_cols; j++) {
simulated_2d_arr[i * num_cols + j] = i * num_cols + j;
}
}
두 가지 방법 모두 용도가 있지만 결과 배열을 2 차원 배열로 작업 할 수있는 함수로 전달할 수 없다는 단점이 있습니다.
void print_2d_arr(size_t rows, size_t cols, int arr[][cols])
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
printf("%5d", arr[i][j]);
}
putchar('\n');
}
}
이 기능은 같은 뭔가를 작동합니다 :
int real_2d_arr[2][3] = { { 1, 2, 3 },
{ 4, 5, 6 } };
하지만 jagged_arr
이전에 대해 작동하지 않습니다 :
즉, 같은 2 차원 배열을 인쇄하는 기능을 고려한다
예상 'INT (*) (sizetype) (COLS)]하지만 인수 형'INT ** '
이다,691 363,210
또는 simulated_2d_arr
위해 동적으로 할당 할 때
예상 'INT (*) (sizetype) (COLS)]하지만 인수 형인'INT * '
올바른 유형 사용 2d 배열은 위의 오류 메시지에서 볼 수 있습니다. int
의 2 차원 배열의 경우 int (*)[]
이됩니다. 이것은 함수 호출을 포함하여 대부분의 표현식에서 2 차원 배열이 붕괴되는 유형입니다. 따라서, 동적 int
s의 2 차원 배열을 할당이 작동합니다 :
는
size_t num_rows = 3;
size_t num_cols = 5;
int (*array_2d)[num_cols] = malloc(sizeof *array_2d * num_rows);
이 num_cols
int
의의 num_rows
배열을위한 공간을 할당합니다. VLA는 생성되지 않지만 VLA 유형이 사용됩니다. 물론 VLA는 C99에서 다시 소개되었지만 C11에서는 선택 사항으로 지정되었습니다 (여전히 널리 지원되지만).
질문의 동적 유형 부분에 대해서는 유형 식별자를 보유하기 위해 enum
을 만들고 이러한 열거 상수 중 하나를 필요로하는 함수에 전달하는 옵션이 있습니다. 이 함수는 (void *)
인수를 받아 들여야하며,이 인수는 형식 열거 형 상수를 기반으로 적절히 변환됩니다. 이것은 좀 더 복잡하지만 여기 예제 프로그램이 있습니다. print_array()
함수는 동적으로 할당 된 배열과 정적으로 크기가 지정된 배열 모두에서 작동합니다. 또한 트리플, 또는 두 배 간접 표시가 필요 없음을 유의하십시오.
#include <stdio.h>
#include <stdlib.h>
enum Type { CHAR,
INT,
FLOAT,
DOUBLE };
void * get_array(enum Type type, size_t rows, size_t cols);
void init_array(enum Type type, size_t rows, size_t cols, void *arr);
void print_array(enum Type type, size_t rows, size_t cols, void *arr);
int main(void)
{
char (*arr_char)[5] = get_array(CHAR, 4, 5);
int (*arr_int)[5] = get_array(INT, 4, 5);
double (*arr_double)[5] = get_array(DOUBLE, 4, 5);
int arr_static[][3] = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };
if (arr_char) { // check for null pointer
init_array(CHAR, 4, 5, arr_char);
puts("4x5 array of char");
print_array(CHAR, 4, 5, arr_char);
putchar('\n');
}
if (arr_int) { // check for null pointer
init_array(INT, 4, 5, arr_int);
puts("4x5 array of int");
print_array(INT, 4, 5, arr_int);
putchar('\n');
}
if (arr_double) { // check for null pointer
init_array(DOUBLE, 4, 5, arr_double);
puts("4x5 array of double");
print_array(DOUBLE, 4, 5, arr_double);
putchar('\n');
}
puts("Statically sized 3x3 array of int");
print_array(INT, 3, 3, arr_static);
putchar('\n');
/* Cleanup */
free(arr_char);
free(arr_int);
free(arr_double);
return 0;
}
/* Returns null pointer on allocation failure */
void *get_array(enum Type type, size_t rows, size_t cols)
{
size_t array_sz = 0;
void *ret = NULL;
switch (type) {
case CHAR:
array_sz = sizeof (char) * rows * cols;
break;
case INT:
array_sz = sizeof (int) * rows * cols;
break;
case FLOAT:
array_sz = sizeof (float) * rows * cols;
break;
case DOUBLE:
array_sz = sizeof (double) * rows * cols;
break;
default:
fprintf(stderr, "Unrecognized type in get_array()");
}
if (array_sz) {
ret = malloc(array_sz);
}
return ret;
}
void init_array(enum Type type, size_t rows, size_t cols, void *arr)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
int offset = i * cols + j;
switch (type) {
case CHAR:
{
char (*array_char)[cols] = arr;
array_char[i][j] = 'a' + offset;
break;
}
case INT:
{
int (*array_int)[cols] = arr;
array_int[i][j] = 0 + offset;
break;
}
case FLOAT:
{
float (*array_float)[cols] = arr;
array_float[i][j] = 0.0 + offset;
break;
}
case DOUBLE:
{
double (*array_double)[cols] = arr;
array_double[i][j] = 0.0 + offset;
break;
}
default:
fprintf(stderr, "Unrecognized type in get_array()");
}
}
}
}
void print_array(enum Type type, size_t rows, size_t cols, void *arr)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
switch (type) {
case CHAR:
{
char (*array_char)[cols] = arr;
printf("%3c", array_char[i][j]);
break;
}
case INT:
{
int (*array_int)[cols] = arr;
printf("%5d", array_int[i][j]);
break;
}
case FLOAT:
{
float (*array_float)[cols] = arr;
printf("%8.2f", array_float[i][j]);
break;
}
case DOUBLE:
{
double (*array_double)[cols] = arr;
printf("%8.2f", array_double[i][j]);
break;
}
default:
fprintf(stderr, "Unrecognized type in get_array()");
}
}
putchar('\n');
}
}
프로그램 출력 :
4x5 array of char
a b c d e
f g h i j
k l m n o
p q r s t
4x5 array of int
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
4x5 array of double
0.00 1.00 2.00 3.00 4.00
5.00 6.00 7.00 8.00 9.00
10.00 11.00 12.00 13.00 14.00
15.00 16.00 17.00 18.00 19.00
Statically sized 3x3 array of int
1 2 3
4 5 6
7 8 9
필요'* (INT *)'? –
GDB를 사용하여 프로그램이 원하는 출력을 제공하지 않거나 충돌이 발생하는 곳을 확인하십시오 –
[this] (https://ideone.com/igYfQQ) – BLUEPIXY