6

Possible Duplicate:
What is the difference between char s[] and char *s in C?
Do these statements about pointers have the same effect?

All this time I thought that whenever I need to copy a string(either literal or in a variable) I need to use strcpy(). However I recently found out this:

char a[]="test";

and this

char *a="test";

From what I understand the second type is unsafe and will print garbage in some cases. Is that correct? What made me even more curious is why the following doesn't work:

char a[5];
a="test";

or this

char a[];
a="test";

but this works however

char *a;
a="test";

I would be greatful if someone could clear up things a bit.

Community
  • 1
  • 1
Pithikos
  • 18,827
  • 15
  • 113
  • 136

3 Answers3

14

char a[]="test";

This declares and initializes an array of size 5 with the contents of "test".

char *a="test";

This declares and initializes a pointer to the literal "test". Attempting to modify a literal through a is undefined behavior (and probably results in the garbage you are seeing). It's not unsafe, it just can't be modified since literals are immutable.

char a[5]; a="test";

This fails even when both a and "test" have the exact same type, just as any other attempt to copy arrays thorugh assignment.

char a[]; a="test";

This declares an array of unknown size. The declaration should be completed before being used.

char *a; a="test";

This works just fine since "test" decays to a pointer to the literal's first element. Attempting to modify its contents is still undefined behavior.

Jeff Widman
  • 22,014
  • 12
  • 72
  • 88
K-ballo
  • 80,396
  • 20
  • 159
  • 169
6

Let's examine case by case:

char a[]="test";

This tells the compiler to allocate 5 bytes on the stack, put 't' 'e' 's' 't' and '\0' on it. Then the variable a points to where 't' was written and you have a pointer pointing to a valid location with 5 available spaces. (That is if you view a as a pointer. In truth, the compiler still treats a as a single custom type that consists of 5 chars. In an extreme case, you can imagine it something like struct { char a, b, c, d, e; } a;)

char *a="test";

"test" (which like I said is basically 't' 'e' 's' 't' and '\0') is stored somewhere in your program, say a "literal's area", and a is pointing to it. That area is not yours to modify but only to read. a by itself doesn't have any specific memory (I am not talking about the 4/8 bytes of pointer value).

char a[5];
a = "test";

You are telling the compiler to copy the contents of one string over to another one. This is not a simple operation. In the case of char a[] = "test"; it was rather simple because it was just 5 pushes on the stack. In this case however it is a loop that needs to copy 1 by 1.

Defining char a[];, well I don't think that's even possible, is it? You are asking for a to be an array of a size that would be determined when initialized. When there is no initialization, it's just doesn't make sense.

char *a;
a = "test";

You are defining a as a pointer to arrays of char. When you assign it to "test", a just points to it, it doesn't have any specific memory for it though, exactly like the case of char *a = "test";

Like I said, assigning arrays (whether null-terminated arrays of char (string) or any other array) is a non-trivial task that the compiler doesn't do for you, that is why you have functions for it.

Jeff Widman
  • 22,014
  • 12
  • 72
  • 88
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • "Then the variable `a` points to where `'t'` was written" - no it doesn't. The variable `a` is an array, it has type `char[5]`, it doesn't point anywhere. The expression `a` decays to a pointer to the first element of that array variable in most contexts. – Steve Jessop Nov 07 '11 at 18:28
  • @SteveJessop, Ok I'm going to edit to be more precise. – Shahbaz Nov 07 '11 at 18:29
3

Do not confuse assignment and initialisation in C, they are different.

In C a string is not a data type, it is a convention, utilising an array and a nul terminator. Like any array, when you assign it, it's name resolves as a mere pointer. You can assign a pointer, but that is not the same as assigning a string.

Clifford
  • 88,407
  • 13
  • 85
  • 165