2017-03-06 2 views
-1

내가 그것을/더 나은 그래서C 변수 크기의 2 차원 배열

// OLD CODE 
int **map; 
     map = calloc(number, sizeof(int *)); 
     if (!(map)) { 
      free(map); 
      return 1; 
     } 
     for (int i = 0; i < number; i++) { 
      map[i] = calloc(number, sizeof(int)); 
      if (!(map[i])) { 
       while (--i >= 0) { 
        free(map[i]); 
       } 
       free(map); 
       return 1; 
      } 
     } 

// NEW CODE 
int (*map)[number] = malloc(sizeof (int[number][number])); 
if (!(map)){ 
    free(map); 
    return 1; 
} 

을 다음과 같이 2-D 변수 배열 할당을 변경 시도하고 더 쉽게 읽을 수 있도록 내 코드를 리팩토링하기 위해 노력하고있어 기능 통과 문제는지도를 사용하는 모든 함수가 int **map이고 IDE에서 알려준 것과 같이지도 선언을 변경함으로써 incorrect type int[]* instead of int** int** 대신 무엇을 사용해야합니까? 함수 선언에 int[]* map을 사용하는 경우 can't resolve variable map

+1

'형 FUNC (INT의 N, INT (* MAP) [N]);''FUNC (번호,지도)를 호출,' – BLUEPIXY

+0

은 자신에게 호의를 수행하고 단지 플랫 배열을 만든 다음 배열을 기준으로 행을 참조하십시오 [y * width + x] = value; –

+0

@MalcolmMcLean 저는 그것에 대해 생각했습니다.지도의 크기를 절반으로 할당 할 수있는 방법이 있으며 색인 순서에 대해 걱정할 필요가 없습니까? 내지도 position [i] [j]와 [j] [i]는 항상 같은 값을 갖지만, i와 j의 순서에 대해 걱정할 필요가 없도록 필요한 크기를 두 배 할당합니다. –

답변

0

아래 코드는 C99 대체 코드 @M.M이 아니라 GCC 확장자입니다. 코드 단순화 int (*map)[number] = malloc(sizeof (int[number][number])); C99 GCC 확장 대안으로서


Undocumented GCC Extension: VLA in struct

기존 기능 세트와의 호환성을 유지하는, 모든 메모리 1 *alloc() 호출 필요한 할당.

이렇게하면 코드가 map으로 완료되면 모든 메모리가 하나의 free(map)과 함께 사용 가능해야합니다. 또한 map[]의 개별 행은 더 이상 재 할당 할 수 없지만 map[] 내에서 스왑 할 수 있습니다.

int **map_allocate(size_t row, size_t column) { 
    struct { 
    int *ip[row];  // Array of pointers, followed by a ... 
    int i[row][column]; // 2D array of int 
    } *u; 
    u = calloc(1, sizeof *u); 
    if (u == NULL) { 
    return NULL; 
    } 
    for (size_t i = 0; i<row; i++) { 
    u->ip[i] = u->i[row]; 
    } 
    return &u->ip[0]; 
} 

주 : 주조 및 필드 없음 i[][]은 올바르게 정렬됩니다.

+0

Structs에는 VLA가 포함될 수 없습니다 –

+0

@ M.M 흥미 롭습니다. 그러나'u'는'struct'가 아니라 하나에 대한 포인터입니다.하지만 충분히 차이가 나지 않을 것으로 기대합니다. 한 컴파일러는 그것을 받아 들였습니다. (또는 그렇게 생각했기 때문에이 포스트를 사용했습니다.) 그리고 다른 하나는 구조체 나 공용체의 멤버가 가변적으로 수정 된 타입을 가질 수 없다고 경고했습니다. 나는 검토 할 것이다. – chux

+0

@ M.M 글쎄, 나는 드로잉 보드로 돌아간 것 같습니다. 너무 나쁘다. 멋진 솔루션처럼 보였다. – chux

0

하는 표준 코드, unlike the other answer 한 할당을 사용하려면, 하나는 포인터와 int 요구의 결합 된 메모리 할당 int 정렬 요구 사항의 특별한 경우에 정렬 우려를 충족 포인터 정렬 사람을 초과하는 것을 보장하기 위해 필요로 조금 까다 롭습니다. 이것은 다음과 같이 long long으로보다 쉽게 ​​표시됩니다.

"코드를 읽기 쉽도록"만드는 것이 OP의 판단으로 남습니다.

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

long long **map_allocate_ll(size_t row, size_t column) { 
    long long **map; 
    long long *ints; 

    size_t pointers_sz = sizeof *map * row; 
    // extend pointer size to `*ints` boundary 
    pointers_sz = (pointers_sz + sizeof *ints - 1)/sizeof *ints * sizeof *ints; 
    size_t ints_sz = sizeof *ints * row * column; 
    printf("psize %zu, isize %zu\n", pointers_sz, ints_sz); 

    map = calloc(1, pointers_sz + ints_sz); 
    if (map == NULL) { 
    return NULL; 
    } 
    ints = (void*) ((char*) map + pointers_sz); 
    printf("map %p\n", (void *) map); 
    for (size_t i = 0; i<row; i++) { 
    map[i] = &ints[i * column]; 
    printf("map[%zu] %p\n", i, (void *) map[i]); 
    } 
    return map; 
} 

int main() { 
    free(map_allocate_ll(5,3)); 
} 

샘플 출력

psize 24, isize 120 
map 0x80081868 
map[0] 0x80081880 
map[1] 0x80081898 
map[2] 0x800818b0 
map[3] 0x800818c8 
map[4] 0x800818e0