使用strcpy()和复制C中char *的地址之间的区别
我有两个动态分配的数组。 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\0"
并且我想将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在他的评论中指出的那样, 内存泄漏不会调用未定义的行为 。
理解这种情况下的[0]和b [0]本身就是数组(或指向字符数组的指针,更准确)
strcpy()
将遍历a [0]指向的字符数组的每个单独元素。 虽然赋值b[0] = a[0]
只会使b [0]指向[0]所指向的位置,导致内存泄漏(b [0]指向的内存不能free
‘d)。
使用像这样的简单图形可视化事态
+---+ --> +------+ +---+---+---+---+---+----+ | a | | a[0] | ------> |'H'|'E'|'L'|'L'|'O'|'\0'| +---+ +------+ +---+---+---+---+---+----+ | 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
所以你永远不能释放它; 内存泄漏。
在这种特殊情况下,它们并不等同。 如果要将[0]分配给b [0],则会有内存泄漏,或者在删除arrays时可以删除相同的内存两次。
所以正确的方法是使用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;
没有任何需要另外分配内存然后释放它。:)