0

I have a struct that has an array of strings (char **args). I need to be able to copy an array of strings (char *input[32]) into that element of the struct. For example:

Thing s;
s.args = input; //assuming input already has some strings in it

When I try to do that, the next time s.args = input is called, it completely overwrites the old input. How can I achieve this functionality in the appropriate manner?

EDIT

This is what the struct looks like.

typedef struct{
char **args;
} Thing;

Then in my function, I have declared:

char *args[512];
.....
args[count] = string //string is a char *

Then finally, I want to do:

s.args = input.
Andrew Backes
  • 1,884
  • 4
  • 21
  • 37

1 Answers1

5

You are not copying it. You are actually just setting the pointer. Effectively you have this:

char **args;
char *other[32];
args = other;

You need to actually copy the array - for that you need to allocate memory for it:

s.args = malloc( 32 * sizeof(char*) );

for( i = 0; i < 32; i++ ) s.args[i] = input[i];

That is a shallow copy - it will copy your string pointers but not duplicate them. If you change the contents of a string in input, that change will be reflected in s.args. To copy the strings, you must do this:

for( i = 0; i < 32; i++ ) s.args[i] = strdup(input[i]);

Since you have allocated memory, then before you overwrite s.args again (and also when your program is finished) you need to free what you allocated. This includes the strings (if you called strdup);

if( s.args != NULL ) {
    // Only do the loop if you did a deep copy.
    for( i = 0; i < 32; i++ ) free(s.args[i]);

    // Free the array itself
    free(s.args);
}
paddy
  • 60,864
  • 6
  • 61
  • 103
  • Oops, I misread one important fact in the question. Have edited to correct my answer. – paddy Sep 18 '12 at 02:30
  • So if I use strdup, the order of what I have to do is like this?: 1) allocat memory 2) free the the allocated space 3) copy with s.args[i] = strdup(input[i]) ? – Andrew Backes Sep 18 '12 at 02:53
  • Yes. Allocate the array first, then `strdup` each string into it. When you're done, `free` the strings first, then the array. – paddy Sep 18 '12 at 02:55
  • Oh, you edited your comment while I was answering the old one. No. You only free pointers that you have allocated (*eg* `malloc` or `strdup`). After you allocate the array, its contents will be undefined. You don't go and free those values until after you have initialised them. – paddy Sep 18 '12 at 02:56
  • Never mind, complete error on my part. Your code is correct. Thank you so much! – Andrew Backes Sep 18 '12 at 03:12
  • 1
    please don't cast the return of `malloc`: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – Jens Gustedt Sep 18 '12 at 06:16
  • Thanks for that @JensGustedt -- I always work with a C++ compiler, and am required to cast when I use `malloc`. I've gotten into the habit of doing so. I will edit the cast out of my answer. – paddy Sep 18 '12 at 22:48