2009-10-30 5 views
0

C에서 가변 크기 이중 스크립트 배열을 만들 수있는 방법이 있습니까 (C++이 아니라 C)? 가변 크기의 단일 스크립팅 된 배열을 만들려면 포인터 만 사용하면됩니다.C에서 변수 크기의 행렬

float *array; 
array = (float *) calloc(sizeof(float), n); 

은 크기가 n 인 float 형식의 단일 스크립트 배열을 만듭니다. 이중 스크립트 배열에서 할 수있는 비슷한 점이 있습니까?

답변

10

C에는 이중 스크립트 배열이 없습니다. 배열의 배열 만 있습니다. 예 : 이 :

int a[3][3]; 

"3x3 ints의 배열"이 아닌 "3 int arrays of 3 ints"로 읽어야합니다. 이것은 표현식 유형에서 즉시 볼 수 있습니다. a[0]은 유효한 표현식이며 유형은 int[3]입니다.

배열 유형의 경우 배열 크기는 유형의 일부이므로 컴파일시 알려야합니다. 이 전통적인 해결 방법이 있습니다

int (*p)[3] // pointer to arrays of 3 ints each 

: 당신이 한 차원 동적으로 만들 수있는 "배열에 대한 포인터 '유형을 가질 수있는 반면 따라서, 나머지 사람들은 여전히 ​​해결되어야 할 것이다

  1. 그냥 너비 x 높이 요소의 1 차원 동적 배열을 사용하고 2D 좌표에서 1D 인덱스를 직접 (y * width + x)으로 계산하십시오. 포인터에

  2. 를 사용하여 포인터 :

    int** a = malloc(sizeof(int*) * height); 
    for (i = 0; i < height; ++i) a[i] = malloc(sizeof(int) * width); 
    a[0][0] = 123; 
    ... 
    

    문제는 여기에 배열이 더 이상 사각형 필요가 없다 것입니다, 그리고 당신이 정말로 그것을 적용 할 수 없습니다. 성능면에서는 연속적인 단일 메모리 블록보다 더 나쁩니다.

C99, 당신은 또한 가변 길이 배열을 사용할 수 있습니다

void foo(int width, int height) { 
    int a[width][height]; 
    ... 
} 
+1

두 번째 방법에서는 배열의 모든 행에 대해 하나의 'malloc'을 수행 할 필요가 없습니다. 하나의 큰 블록에 할당 한 다음 행 포인터를 해당 할당 내의 위치에 할당 할 수 있습니다. – caf

+0

옵션 1의 추가 예제는 여기 내 대답보기 http://stackoverflow.com/questions/3063085/declaring-two-large-2d-arrays-gives-segmentation-fault/3063693#3063693 – Spudd86

5

다차원 배열의 경우 거의 동일한 작업을 수행 할 수 있습니다.

float **array; 
array = calloc(sizeof(float*), n); 
for(int i = 0; i < n; i++) 
{ 
    array[i] = calloc(sizeof(float), n); 
} 
+0

예를 들어 배열 [2] [3] = 5를 호출 할 수 있습니까? 물론, n> 3이라고 가정합니다. – wolfPack88

+0

2 중 배열'double [] [] '은 메모리의 단일 세그먼트를 차지하지만, 각 행에 대한 세그먼트에 대한 포인터의 배열을 저장합니다. 물론, 배열의 첨자를 사용하여 접근 할 수는 있지만, 똑같은 것은 아닙니다. – Cascabel

+0

@ wolfPack88 : 네, 그렇지만 어떻게 작동하는지 이해하겠습니다. 'array [2]'는 배열에 저장된 세 번째'float *'포인터이고'array [3]'은'array [2]'가 가리키는 메모리에 저장된 네 번째'float'을 사용합니다. – Cascabel

4

는 n 행과 m 열을 가진 행렬은 다음 각 인덱스 i

row = i/n 
col = i % n 

및 역 매핑

을 나타내고,이를 나타 내기 길이 m*n의 선형 어레이를 사용하려면
i = row * n + col 

matlab과 같은 행렬을 사용하는 대부분의 대수 패키지는 실제로이 표현을 사용합니다. 왜냐하면 어떤 대다수의 일반화에도 잘 맞기 때문입니다. ould는이를 3 차원 행렬로 일반화합니다).

2

아니, 그건 불가능합니다. 또는 하나의 배열을 할당하고 좌표를 가져 와서 배열에 인덱스를 반환하는 인덱싱 함수를 정의 할 수 있습니다.

int Index(int i, int j, int numCols) 
{ 
    return i * numCols + j; 
} 

int numRows = 100; 
int numCols = 200; 

float *data = malloc(sizeof(float) * numRows * numCols); 

data[Index(34, 56, numCols)] = 42.0f; 
+0

나는 * data + 34 * 200 + 56) = 42.0f ... 나는 일반적으로 더 많은 문학적 스타일을 선호한다. – mch

1

당신은 C99 가변 길이 배열을 (GCC와 함께 작동)를 사용할 수 있습니다 :

#include <stdio.h> 
#include <stdlib.h> 

void foo(size_t rows, size_t cols, float array[rows][cols]) 
{ 
    printf("%f\n", array[2][3]); 
} 

int main(void) 
{ 
    size_t rows = 4; 
    size_t cols = 5; 
    float (*array)[cols] = calloc(sizeof (float), rows * cols); 
    array[2][3] = 42; 
    foo(rows, cols, array); 
} 
+0

"C99 가변 길이 배열을 사용할 수 있습니다." 그러나 제발하지 마. :) – BobbyShaftoe

+0

@Bobby : 컴파일러에서 지원하지 않는 이유는 알지 못합니다. 특히 스택 할당이 포함되지 않은 경우와 같이 ... – Christoph

1

나는 아무도가 하나의 연속적인 할당을 보존 '명백한'대안을 지적하지 않았다 놀랐어요 주 매트릭스,하지만 두 번 subscripting 포인터를 벡터가 있습니다. (. 나는 그게 결국하지 분명 의미 가정 해 봅시다)

float **array2d = malloc(sizeof(*array2d) * height); 
float *array1d = malloc(sizeof(*array1d) * height * width); 

for (i = 0; i < height; ++i) 
    array2d[i] = &array1d[i * width]; 

이제 2 차원 배열을 기록 할 수는 평소와 같이 액세스 :

array2d[0][0] = 123.0; 

을 분명히, 우리는 또한 메모리를 확인해야 배당.

관련 문제