4

Lately I've been learning all about the C language, and am confused as to when to use

char a[];

over

char *p;

when it comes to string manipulation. For instance, I can assign a string to them both like so:

char a[] = "Hello World!";
char *p = "Hello World!";

and view/access them both like:

printf("%s\n", a);
printf("%s\n", p);

and manipulate them both like:

printf("%c\n", &a[6]);
printf("%c\n", &p[6]);

So, what am I missing?

Nathan Bishop
  • 623
  • 1
  • 5
  • 11
  • 3
    first of all, enable compiler warnings – Karoly Horvath Oct 09 '14 at 13:33
  • Use whichever you want... is just syntactic sugar en.wikipedia.org/wiki/Syntactic_sugar – zambotn Oct 09 '14 at 13:34
  • You miss the most important point which is the memory release, how long you want your object a to live in your program. – Martin Oct 09 '14 at 13:34
  • 9
    @zambotn: you're wrong. they are different. – Karoly Horvath Oct 09 '14 at 13:34
  • @Karoly Horvath not for the code above. BTW you are right, in general case is not the same. – zambotn Oct 09 '14 at 13:35
  • possible duplicate of [char \*array and char array\[\]](http://stackoverflow.com/questions/20347170/char-array-and-char-array) also: your last `printf` calls are wrong, and you can't manipulate the value `p` points to, because it's an implicit `const char *`, pointing to read-only memory – Elias Van Ootegem Oct 09 '14 at 14:10

2 Answers2

9
char a[] = "Hello World!";

This allocates modifiable array just big enough to hold the string literal (including terminating NUL char). Then it initializes the array with contents of string literal. If it is a local variable, then this effectively means it does memcpy at runtime, every time the local variable is created.

Use this when you need to modify the string, but don't need to make it bigger.

Also, if you have char *ap = a;, when a goes out of scope ap becomes a dangling pointer. Or, same thing, you can't do return a; when a is local to that function, because return value will be dangling pointer to now destroyed local variables of that function.

Note that using exactly this is rare. Usually you don't want an array with contents from string literal. It's much more common to have something like:

char buf[100]; // contents are undefined
snprintf(buf, sizeof buf, "%s/%s.%d", pathString, nameString, counter);

char *p = "Hello World!";

This defines pointer, and initializes it to point to string literal. Note that string literals are (normally) non-writable, so you really should have this instead:

const char *p = "Hello World!";

Use this when you need pointer to non-modifiable string.

In contrast to a above, if you have const char *p2 = p; or do return p;, these are fine, because pointer points to the string literal in program's constant data, and is valid for the whole execution of the program.


The string literals themselves, text withing double quotes, the actual bytes making up the strings, are created at compile time and normally placed with other constant data within the application. And then string literal in code concretely means address of this constant data blob.

hyde
  • 60,639
  • 21
  • 115
  • 176
  • 2
    One clarification might be helpful (or may just cause confusion). In either case, the compiler will create a string literal and add it to the executable. In the case of the array, the array is initialized at runtime (eg, the 'memcpy' you refer to happens at runtime, while the creation of the string literal happens at compile time.) The pointer is also initialized at runtime, but the initialization doesn't copy the string--just its address. – William Pursell Oct 09 '14 at 13:38
  • @WilliamPursell Edited a bit based on your suggestion – hyde Oct 09 '14 at 13:58
  • So, if I was to compare this to PHP (being more familiar with), would I be right to assume that ```char *p;``` is similar to a PHP constant, and ```char a[];``` would be a normal PHP variable? – Nathan Bishop Oct 09 '14 at 15:54
  • 1
    @NathanBishop I think that is dangerous thinking. C does not have "real" strings same way PHP (and almost everything else) has. Better think of C strings as C strings: Pointers to memory somewhere, which may be constant, may be in static data, stack or heap, and should have terminating NUL in it. – hyde Oct 09 '14 at 16:06
  • @NathanBishop I added a bit of text, which may help with understanding `a`. – hyde Oct 09 '14 at 16:56
2

char * strings are read-only. They cannot be modified while char[] strings can be.

char *str = "hello"; str[0] = 't'; // This is an illegal operation

Whereas

char str[] = "hello"; str[0] = 't'; // Legal, string becomes tello

rohit89
  • 5,745
  • 2
  • 25
  • 42
  • 2
    "`char *` strings are read-only" Only if you set them equal to a string literal (as he did in the example). They are perfectly writable otherwise. – wolfPack88 Oct 09 '14 at 13:38
  • 1
    A `char *` never is read-only, because it's not a `const char const *`, but it can be made to point to `const char`, which is of course read-only. As ever: specifying the storage class makes it all clear – Elias Van Ootegem Oct 09 '14 at 14:13