views:

222

answers:

3

I'm using C for a class project for the first time after first learning C++, so syntax is killing me... Basically, I need to store a string given by a function into a separate variable for later use.

I have an array of chars declared like this

char foo[];

A function that I'm given assigns a bunch of characters into this array (or pointers to characters?). I can print out the actual string stored in foo like this

printf("%s", foo);

And I can store its address in a different variable like this

char *bar;

bar = &foo[0];

printf("%s", foo);

The full string is output just fine in both cases. However, how can I store this string in a different variable? If foo changes, then bar will no longer hold the string I need since it is just pointing to foo. Anything I have thought of gives me compiler errors like

warning: initialization makes pointer from integer without a cast

Hopefully that's enough info. Thanks for the help in advance.

+6  A: 

You need to copy the string.

Easiest way is with heap allocations:

char *bar = strdup(foo);

Don't forget to free that allocation when you are done with it:

free(bar);

If you don't want to use heap allocations, you can create a buffer on the stack and manually copy it in. You do want to be careful that you don't overflow the buffer (and that your buffer is 0 terminated, strncpy won't do that for you if your src is longer then your dest):

char copy[SOMESIZE];
strncpy(copy, foo, sizeof(copy) - 1);
copy[sizeof(copy) - 1] = '\0';    

If you have variable length array support, you can use that:

char copy[strlen(foo) + 1];
strcpy(copy, foo);

As Christoph correctly noted in the comments, strdup is not part of the C standard. If you're using Windows, you'll want to use _strdup. If you want to be absolutely portable, you can implement strdup quite easily:

char *strdup(const char *orig)
{
    char *copy = (char *)malloc(strlen(orig) + 1);
    if (copy != NULL)
        strcpy(copy, orig);

    return copy;
}
R Samuel Klatchko
+1; keep in mind that `strdup()` is POSIX and not part of the ISO-C standard library, so you might have to re-implement it yourself if you want maximal portability
Christoph
@Christoph - thanks. Posix has been my primary development platform for so long I forget the difference. Anyway, updated my answer to give some more info on that.
R Samuel Klatchko
Christoph
A: 

use strcpy function to copy string to another variable.

char *myStringVar;

strcpy(myStringVar, your_Function_Returning_String() )

Allocate memory for myStringVar if returned string is out of scope.

EDIT:

char *myStringVar = (char *)malloc(BUFFER_SIZE);
Manav MN
`strcpy()` expects a buffer of sufficient size as the target, not an uninitialized pointer
sth
-1: as you failed to allocate memory, this'll overwrite whatever random location the uninitialized variable points to
Christoph
Still if i want to use strcpy only for the above problem, what changes should be made for strcpy to work properly ?
Manav MN
@Manav - you need to make sure myStringVar points to valid memory. You can change that to a stack allocation `char myStringVar[SIZE]` (although you need to be careful about buffer overflow) or you can allocate it on the heap `char *myStringVar = malloc(strlen(src) + 1)` (and you need to check that malloc does not return NULL).
R Samuel Klatchko
A: 

You need to copy the string using strncpy or duplicate it using strdup:

char foo[] = "Hello World";
char* bar = strdup(foo);

foo[0] = 'B';
printf("%s", foo);
printf("%s", bar);

free(bar); // Don't forget to release the memory!

Prints:

Bello World
Hello World

Or, if you already have a string you want to copy into:

char foo[] = "Hello World";
char bar[] = "Goodbye Cruel World";

strncpy(bar, foo, sizeof(bar)-1); 

foo[0] = 'B';
printf("%s", foo);
printf("%s", bar);

Also rints:

Bello World
Hello World

The third argument to strncpy is the maximum number of characters to copy (to prevent overflow) Note that it is one less than the length of the bar buffer so that bar can be nul-terminated. Also note that sizeof only works here because bar is a local array. It does not work on char*, in that case you need to know the size externally, e.g.:

char foo[] = "Hello World";
size_t bar_len = 20;
char* bar = (char*)malloc(bar_len);

strncpy(bar, foo, bar_len-1); // CANNOT use sizeof(bar) here!

foo[0] = 'B';
printf("%s", foo);
printf("%s", bar);

free(bar); // Don't forget!
Tyler McHenry
strncpy is not a good way to do this. strncpy *always* copies n characters, even if the string being copied is shorter, padding with 0 chars, wasting cycles. Additionally strncpy does not guarantee that the written string is 0 terminated, if the source string is longer than the length of the buffer it just gets truncated, without a terminating 0. And the -1 does not help here because malloc does not guarantee zeroed memory.
wich