2014-01-11 43 views
1

我需要实现一个简单的指向一个typedef指针的动态指针数组。
每次用户请求时使用realloc,数组的大小将按sizeof(指针)增长。
所以我有是这样的:在调用realloc之后,是否需要初始化(设置为0)内存?

#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; 
} 

这给出了以下的输出:

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) 

我所关心的第三元素,其含量。
这就是为什么我问是否应该在新的realloc后设置为0的内存。

编辑:
所以,指出C的标准,由H2CO3,新的呼叫到realloc的,就是:
nodes = realloc(nodes, (i+1)*sizeof(node));
而在这之后的initiallization,我这样做: nodes[i] = NULL
这也工作得很好。

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()'将复制原先在缓冲区中的内容。如果新块大于原始块,则末尾的元素(即原始数组中未存在的元素)将被初始化。 – 2014-01-11 20:05:16

+0

@ H2CO3:新块肯定比旧块大,所有以前的数据都丢失了? – Chris

+0

Naw。再次阅读我的评论。多余的元素将被初始化,保存内存块开始处的原始内容。 – 2014-01-11 20:16:40

回答

5

嗯,这要看情况。你要求内存初始化为0?如果不是,那么不,你不需要做任何事情。与malloc的情况一样,realloc不执行任何初始化。原始块中存在的任何内存都未初始化。

+0

所以我应该为每次添加的特定新元素调用memset? – Chris

+0

好吧,再一次,这一切取决于是否需要您初始化此内存。如果是这样,那么是的。然而,重要的是要认识到C不能保证空指针由全零位表示,只是它将* *等于'0'。一个微妙但重要的区别。 –

1

去通过的realloc的定义()

realloc的(无效* P,为size_t大小)改变对象的大小指出 由psize。内容将保持不变,直到旧的和新的尺寸的最小值。如果新尺寸较大,则新空间为 未初始化。 (来自Kernighan和Ritchie)

您可能需要初始化新空间。你可以在确定void *所指向的地址是什么类型的数据的时候这样做。

2

请注意,空指针不必等于C中的立即数0,它只能保证不等于任何有效指针。另外,对于不同的指针类型(例如函数指针与char指针),技术上允许空指针是不同的。

因此,简单地将内存初始化为零可能会调用未定义的行为。

所以初始化为NULL,将是正确的!这就是我所做的!克里斯 -

不,你会做的就是投空这样的:(无效*)NULL,写这个内存位置。但是你从来没有真正写过你的malloc(通过传递NULL给realloc)。你基本上只是在你的printf中读取未初始化的内存(这是未定义的行为)。

+0

因此初始化为NULL,将是正确的!这就是我所做的! – Chris

+0

你能解释一下(void *)NULL和NULL之间的区别吗?我已经使用了这两个程序并运行了valgrind程序并没有发生错误。另外,为什么我不写信给我分配的记忆?我已经发布了main的更新,如果你运行它,你会看到nodes [1]输出'c'变量的地址并且打印'*(nodes [i])'我得到'c '。 – Chris

+0

@Chris:如果在某些体系结构上,nullptr!= 0,那么编译器必须知道将适当的值放入内存中。它必须知道内存的引用位将被视为一个指针。如果不同的指针类型具有不同的nullptr值,编译器还必须知道它需要写入内存的空指针的* type *类型。 – EOF

相关问题