我有两个动态分配的数组。c
char **a = (char**)malloc(sizeof(char*) * 5));
char **b = (char**)malloc(sizeof(char*) * 5));
for (int i = 0; i < 7, i++) {
a[i] = (char*)malloc(sizeof(char)*7);
b[i] = (char*)malloc(sizeof(char)*7);
}
如果a[0]
是"hello "
,并且我想将a[0]
复制到b[0]
,那么strcpy
和指针分配是一样的吗?例如:
strcpy(b[0], a[0])
b[0] = a[0]
这两者会做同样的事情吗?
否。两者并不相同。在这种情况下,strcpy(b[0], a[0])
是将a[0]
指向的字符串复制到b[0]
的正确方式。
在b[0] = a[0]
的情况下,分配给b[0]
的内存将丢失,这将导致内存泄漏。现在释放a[0]
和b[0]
将调用未定义的行为。这是因为它们都指向相同的内存位置,而您两次释放相同的已分配内存。
注意:应该注意的是,正如Matt McNabb在评论中指出的,内存泄漏不会调用未定义的行为。
理解在这种情况下a[0]和b[0]本身就是数组(或者更准确地说是指向字符数组的指针)
CCD_ 15将遍历a[0]所指向的字符数组的每个单独元素。而赋值b[0] = a[0]
只会使b[0]指向a[0]所在的位置,从而导致内存泄漏(b[0]所指向的内存不能是free
'd)。
使用这样一个简单的数字来可视化事务的状态-
+---+ --> +------+ +---+---+---+---+---+----+
| a | | a[0] | ------> |'H'|'E'|'L'|'L'|'O'|' '|
+---+ +------+ +---+---+---+---+---+----+
| a[1] |
+------+
| ... |
+------+
| a[n] |
+------+
它们是不同的。在strcpy()的情况下,复制字符,在赋值的情况下调整指针以指向同一数组。
a[0] -> allocated memory containing "hello"
b[0] -> allocated memory not yet initialised
之后b[0]=a[0]
现在两者都指向相同的内存
a[0] -> allocated memeory containing "hello"
b[0] ---^
更糟糕的是,现在没有任何东西指向b[0]的
allocated memory not yet initialised
所以你永远无法解放它;内存泄漏。
在这种特殊情况下,它们是不等价的。如果将a[0]分配给b[0],则会出现内存泄漏,或者在删除阵列时,同一内存可能会被删除两次。
因此,正确的方法是使用函数strcpy
。
考虑到你的例子中有一个拼写错误。代替
for (int i = 0; i < 7, i++) {
a[i] = (char*)malloc(sizeof(char)*7);
b[i] = (char*)malloc(sizeof(char)*7);
}
应该有
for (int i = 0; i < 5, i++) {
a[i] = (char*)malloc(sizeof(char)*7);
b[i] = (char*)malloc(sizeof(char)*7);
}
然而,在某些情况下,使用指针分配要简单得多。考虑交换"同一"动态分配数组的两行的任务。例如,让我们假设我们想要交换a[0]
和a[4]
。我们可以使用strcpy
以以下方式完成任务
char *tmp = malloc( 7 * sizeof( char ) );
strcpy( tmp, a[0] );
strcpy( a[0], a[4] );
strcpy( a[4[, tmp );
free( tmp );
然而,只交换指针会简单得多:)
char *tmp = a[0];
a[0] = a[4];
a[4] = tmp;
没有任何必要重新分配额外的内存,然后释放它。:)