Difference between using strcpy() and copying the

2020-02-07 04:34发布

问题:

I have two dynamically allocated arrays. 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);
}

If a[0] was "hello\0" and I wanted to copy a[0] to b[0], would strcpy and pointer assignment be the same thing? For example:

  1. strcpy(b[0], a[0])
  2. b[0] = a[0]

Would these both do the same exact thing?

回答1:

NO. Both are not same. In this case, strcpy(b[0], a[0]) is correct way to copy the string pointed by a[0] to b[0].

In case of b[0] = a[0], memory allocated to b[0] will lost and it will cause memory leak. Now freeing both of a[0] and b[0] will invoke undefined behavior. This is because both of them are pointing to same memory location and you are freeing same allocated memory twice.


NOTE: It should be noted that, as Matt McNabb pointed in his comment, memory leak does not invokes undefined behavior.



回答2:

Understand that a[0] and b[0] in this case are themselves arrays (or pointers to characters arrays, to be more precise)

strcpy() would traverse through each individual element of the character array which a[0] points to. While the assignment b[0] = a[0] will just make b[0] point where a[0] is pointing, resulting in memory leak (the memory to which b[0] was pointing cannot be free'd).

Visualize the state of affairs using a simple figure like this -

     +---+ -->  +------+          +---+---+---+---+---+----+
     | a |      | a[0] | ------>  |'H'|'E'|'L'|'L'|'O'|'\0'| 
     +---+      +------+          +---+---+---+---+---+----+
                | a[1] |
                +------+
                | ...  |
                +------+    
                | a[n] |
                +------+                                    


回答3:

They are different. In strcpy() case you are copying the characters, in the assignment case you adjust the pointer to point to the same array.

 a[0] -> allocated memory containing "hello"
 b[0] -> allocated memory not yet initialised

After b[0] = a[0]

both now point to same memory

 a[0] -> allocated memeory containing "hello"
 b[0] ---^ 

and worse nothing now points to b[0]'s

 allocated memory not yet initialised

so you can never free it; memory leak.



回答4:

In this particular case they are not equivalent. If to assign a[0] to b[0] then there will be a memory leak or the same memory can be deleted twice when the arrays will be deleted.

So the correct approach is to use function strcpy.

Take into account that there is a typo in your example. Instead of

for (int i = 0; i < 7, i++) {
  a[i] = (char*)malloc(sizeof(char)*7);
  b[i] = (char*)malloc(sizeof(char)*7);
}

there shall be

for (int i = 0; i < 5, i++) {
  a[i] = (char*)malloc(sizeof(char)*7);
  b[i] = (char*)malloc(sizeof(char)*7);
}

However there are situations when it is much simpler to use pointer assignments. Consider task of swapping of two rows of the "same" dynamically allocated array. For example let's assume that we want to swap a[0] and a[4]. We could do the task the following way using strcpy

char *tmp = malloc( 7 * sizeof( char ) );

strcpy( tmp, a[0] );
strcpy( a[0], a[4] );
strcpy( a[4[, tmp );

free( tmp );

However it will be much simpler to swap only pointers:)

char *tmp = a[0];
a[0] = a[4];
a[4] = tmp;

There is no any need to alloocate additionally memory and then to free it.:)