2014-01-11 5 views
1

typedef'ed 포인터에 대한 포인터의 간단한 동적 배열을 구현해야합니다.
사용자가 요청할 때마다 realloc을 사용하면 배열 크기가 sizeof (pointer)만큼 증가합니다.
는 그래서 내가 가진 것은 이것이다 :realloc을 호출 한 후 메모리를 초기화 (0으로 설정)해야합니까?

Done reallocating 
0  (nil) 
1  (nil) 
2  (nil) 
3  0x20fe1 
4  (nil) 
5  (nil) 
6  (nil) 
7  (nil) 
8  (nil) 
9  (nil) 
10  (nil) 
11  (nil) 
12  (nil) 
13  (nil) 
14  (nil) 
15  (nil) 
16  (nil) 
17  (nil) 
18  (nil) 
19  (nil) 

내가 3 요소에 대한 걱정, 그 내용 :

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
typedef void* node; 

void printmem(node* a, int c) { 
    int i; 
    for (i = 0; i < c; ++i) 
    { 
     printf("%d\t\t%p\n", i, a[i]); 
    } 
} 

int main(void) { 
    node* nodes = NULL; 
    int i = 0, count = 20; 

    for (i = 0; i < count; ++i) 
    { 
     nodes = realloc(nodes, sizeof(node)); 
    } 
    printf("Done reallocating\n"); 
    printmem(nodes, i); 
    // free(a); 
    return 0; 
} 

이 다음과 같은 출력을 제공합니다.
그래서 새로운 realloc 후에 메모리를 0으로 설정해야하는지 묻습니다.

편집 : C의 표준에 지적
그래서, H2CO3에 의해, realloc 함수에 새 호출은 다음과 같습니다 nodes[i] = NULL
: nodes = realloc(nodes, (i+1)*sizeof(node));
그리고 initiallization에 대한 그 후
, 내가 이런 짓을 그것은 또한 잘 작동했습니다.

Edit2가 :
지금이 있습니다

int main(void) { 
    node* nodes = NULL; 
    int i = 0, count = 20; 

    for (i = 0; i < count; ++i) 
    { 
     nodes = realloc(nodes, (i+1)*sizeof(node)); 
     nodes[i] = NULL; 
     if (i == 1) { 
      nodes[i] = &count; 
     } 
    } 
    printf("Done reallocating\n"); 
    printmem(nodes, i); 
    printf("\t*nodes[1] == %d\n", *(int*)nodes[1]); 
    printf("\tAddress of count is %p\n", &count); 
    // free(a); 
    return 0; 
} 
+1

'realloc()'은 원래 버퍼에 있던 내용을 복사합니다. 새로운 블록이 원래 블록보다 크다면, 최종 블록의 요소 (즉, 원래의 배열에 존재하지 않는 요소)는 초기화되지 않을 것이다. –

+0

@ H2CO3 : 새 블록은 이전보다 큽니다. 따라서 이전의 모든 데이터가 손실됩니까? – Chris

+0

Naw. 한 번 더 내 의견을 읽으십시오. 초과 요소는 초기화되지 않고 메모리 블록의 시작 부분에있는 원본 내용이 보존됩니다. –

답변

5

글쎄, 모든 것이 달려있다. 이면 메모리가 0으로 초기화되어야합니까? 그렇지 않다면, 아무 것도 할 필요가 없습니다. malloc의 경우와 마찬가지로 realloc은 초기화를 수행하지 않습니다. 원래 블록에 있던 메모리를 지나간 모든 메모리는 초기화되지 않은 채로 남아 있습니다.

+0

그래서 매번 추가되는 특정 새 요소에 대해 memset을 호출해야합니까? – Chris

+0

음, 다시 말하지만,이 메모리가 초기화 될 필요가 있는지 여부에 따라 달라집니다. 그렇다면 예. 그러나, C가 널 포인터가 모든 0 비트로 표현된다는 것을 보장하지 않는다는 것을 깨닫는 것이 중요하다. 단지 '0'과 비교할 것이다. 미묘하지만 중요한 차이. –

1

realloc을 정의()

으로 realloc (공극 * p를이 size_t 크기)로가는 개체의 크기에 sizep 의해 지적 변경한다. 내용은 이전 및 새 크기의 최소값까지 변경되지 않습니다. 새 크기가 더 크면 새 공간은 초기화되지 않은 것입니다. (Kernighan and Ritchie)

새 공간을 초기화해야 할 수도 있습니다. void *가 가리키는 주소가 어떤 종류의 데이터인지 결정할 때 그렇게 할 수 있습니다.

2

null-pointer는 C에서 리터럴 0과 같을 필요는 없습니다. 단지 유효한 포인터와 같지 않음을 보증합니다. 또한 null 포인터는 기술적으로 다른 포인터 유형 (예 : 함수 포인터 대 char 포인터)에 따라 달라질 수 있습니다.

따라서 메모리를 0으로 초기화하면 정의되지 않은 동작이 호출 될 수 있습니다.

NULL로 초기화하면 올바를 것입니다! 그게 내가 한 짓이야! - 크리스

아니, 당신은 할 수이 될지 캐스팅과 같이 널 (null) : (무효 *) NULL, 메모리 위치에이 물품.하지만 실제로는 메모리에 쓰지 않는다. (realloc에 ​​NULL을 전달하는 것). 기본적으로 printf에서 초기화되지 않은 메모리 (정의되지 않은 동작)를 읽는 것입니다.

+0

그래서 NULL로 초기화하면 정확합니다! 그게 내가 한 짓이야! – Chris

+0

(void *) NULL과 NULL의 차이점을 설명해 주시겠습니까? 나는 둘 다 사용하고 valgrind 프로그램과 함께 달렸고 에러가 발생하지 않았습니다. 또한, 내가 할당 한 기억에 왜 쓰지 않을 것인가? 메인에 업데이트를 게시했습니다. 노드를 실행하면 [1]은'c' 변수의 주소를 출력하고'* (nodes [i]) '를 출력하면'c '. – Chris

+0

@Chris : 일부 아키텍처에서 nullptr! = 0이면 컴파일러는 적절한 값을 메모리에 저장해야합니다. 그것은 메모리의 참조 된 비트가 포인터로 취급된다는 것을 알아야합니다. 다른 포인터 유형이 다른 nullptr 값을 가지면 컴파일러는 메모리에 쓸 필요가있는 null 포인터의 * type *을 알아야합니다. – EOF