views:

125

answers:

5

hey, here's my code

#include <stdio.h>
#include <string.h>

int main()
{
        char *array[10]={};
        char* token;
        token = "testing";
        array[0] = "again";
        strcat(array[0], token);
}

why it returns Segmentation fault?

I'm a little confused.

A: 

To create a array of characters, char *array[10]={}; should instead be char array[10]={};

the segmentation fault occurs because array[0] points to "again", a string literal, and modifying string literals is a no-no(undefined behaviour)

Bwmat
well, thanks a lot, but how can i create a string array then?
According to http://home.netcom.com/~tjensen/ptr/ch8x.htm `array` is array of 10 pointers to char, not a pointer to array. `sizeof()` of that construct is also equal to `8 * sizeof(char *)`.
che
whoops, I always get confused by this stuff. Either way, a simple char array is what he needed
Bwmat
That would have to be a `char array[10][20]` (10 strings of up to 19 characters). See http://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/CONCEPT/arrays.html !
Carl Smotricz
A: 

If you're planning on changing the strings involved you should really allocate enough memory for what you need. For example instead of char *token; token = "testing"; you could use, say char token[20] = "testing";, which allows enough room for a 19 character string (plus the null byte at the end).

Similarly, you could use char array[10][20] = {"testing"}; to create an array of 10 strings and set the first one to testing.

+2  A: 

How this works: char *array[10] is an array of 10 char * pointers (basically 10 same things as token).

token = "testing" creates static space somewhere in your program's memory at build time, and puts "testing" there. Then in run time, it puts address to that static "testing" to token.

array[0] = "again" does basically the same thing.

Then, strcat(array[0], token) takes address in array[0], and tries to add token's content to string at that address. Which gives you segfault, since array[0] points to read-only data segment in your memory.

How to do this properly:

char * initial = "first"; // pointer to static "first" string
char * second = "another"; // another one
char string[20]; // local array of 20 bytes

strcpy(string, initial); // copies first string into your read-write memory
strcat(string, second); // adds the second string there

Actually, if you don't want to shoot yourself in the foot, the better way to do something like the last two lines is:

snprintf(string, sizeof(string), "%s%s", initial, second);

snprintf then makes sure that you don't use more than 20 bytes of string. strcat and strcpy would happily go over the limit into invalid memory, and cause another run-time segfault or something worse (think security exploits) if the copied string were longer then the destination space.

che
+5  A: 

Technically, this isn't valid C. (It is valid C++, though.)

char *array[10]={};

You should use

char *array[10] = {0};

This declares an array of 10 pointers to char and initializes them all to null pointers.

char* token;
token = "testing";

This declares token as a pointer to char and points it at a string literal which is non-modifiable.

array[0] = "again";

This points the first char pointer of array at a string literal which (again) is a non-modifiable sequence of char.

strcat(array[0], token);

strcat concatenates one string onto the end of another string. For it to work the first string must be contained in writeable storage and have enough excess storage to contain the second string at and beyond the first terminating null character ('\0') in the first string. Neither of these hold for array[0] which is pointing directly at the string literal.

What you need to do is something like this. (You need to #include <string.h> and <stdlib.h>.)

I've gone for runtime calculation of sizes and dynamic allocation of memory as I'm assuming that you are doing a test for where the strings may not be of known size in the future. With the strings known at compile time you can avoid some (or most) of the work at compile time; but then you may as well do "againtesting" as a single string literal.

char* token = "testing";
char* other_token = "again";

/* Include extra space for string terminator */
size_t required_length = strlen(token) + strlen(other_token) + 1;

/* Dynamically allocated a big enough buffer */
array[0] = malloc( required_length );
strcpy( array[0], other_token );
strcat( array[0], token );

/* More code... */

/* Free allocated buffer */
free( array[0] );
Charles Bailey
If you're using GNU extensions, you can shorten all of that length checking, allocating and copying to `asprintf(`
che
A: 

U r putting a string at array[0] position which is only one character use array[0]='a' like that

sagar
Er...no it isn't, sagar. `array[0]` is a `char *`, not a `char`. While it is legal to store a `char` constant in a `char *` variable, it isn't very good practice. (Your answer was not downvoted by me, but perhaps I ought to have done so.)
Brian Hooper