1

In C, we can make a pointer to a constant string like

char *s = "abc";

But since strings are basically null terminated character arrays, why isn't this allowed?

char *s = {'a', 'b', 'c' , '\0' };
5
  • 2
    The first is a string literal, the second is a char array. Commented Jul 28, 2013 at 18:14
  • 1
    Isn't a string literal also internally a char array? Commented Jul 28, 2013 at 18:15
  • 2
    a string literal is a pointer (to const char) - pointers are not the same as arrays (even though they can often be treated in the same way). Commented Jul 28, 2013 at 18:22
  • You can't initialize an array with the pointer, right? Why should you be able to initialize a pointer with an array then? Arrays are not pointers, and pointers are not arrays. Array expressions decay to pointer expressions, but you should not assume you can do everything with pointers and arrays the same way. :-) Commented Jul 28, 2013 at 18:31
  • 1
    @PaulR: No, a string literal is an expression of type char[N+1], where N is the length. It decays to a pointer in most contexts. And C string literals are not const, though attempting to modify one has undefined behavior. Commented Jul 28, 2013 at 18:38

3 Answers 3

10

It's basically because the language doesn't allow it.

A string literal is an expression of type char[N+1], where N is the length of the literal. It refers to an anonymous array object with static storage duration, meaning that the object exists for the entire execution of the program.

(Note that, unlike in C++, it's not const char[N+1], but attempting to modify it has undefined behavior.)

And like any expression of array type, it's implicitly converted to a pointer to the array's first element in most contexts.

So in this declaration:

char *s = "abc";

the expression "abc" is implicitly converted to a pointer to the first character of the array, which is used to initialize s. But it's much safer to write it like this:

const char *s = "abc";

so that you don't accidentally attempt to modify the array.

So why doesn't this work?

char *s = { 'a', 'b', 'c', '\0' };

It's because { 'a', 'b', 'c', '\0' } is not an expression. It's an initializer, and can be used to initialize an array object, but it can't be used to initialize a pointer object. If you instead write:

char arr[] = { 'a', 'b', 'c', '\0' };

then the initializer is used to initialize the array object; it doesn't create an array object. For the char *s version to work, it would have to create an object for the pointer s to point to. Brace-enclosed initializer lists just don't do that.

C99 added a new feature, compound literals, that are in some ways similar to string literals but more general. For example, this:

(char[]){ 'a', 'b', 'c', '\0' }

is an expression of type char[4] -- and again, like any expression of array type, it's implicitly converted to a pointer in most contexts. So this:

char *arr = (char[]){ 'a', 'b', 'c', '\0' };

is valid and makes arr point to the first element of the anonymous array object created by the compound literal.

There is one significant difference: the lifetime of that array object is not necessarily static. If a compound literal appears outside any function, the array object does exist for the entire execution of the program; otherwise, it acts like a local object with automatic storage duration.

If you're using a compiler that doesn't support C99 (*cough*Microsoft*cough*), you can always declare an array object first:

const char arr[] = { 'a', 'b', 'c', '\0' };
const char *s = arr;

See also section 6 of the comp.lang.c FAQ, which discusses arrays and pointers (and does an excellent job of clearing up some of the common misconceptions about them).

Sign up to request clarification or add additional context in comments.

Comments

8

This is because a pointer is not an array. (You can have an array decay to a pointer that points to the address of the first element, but that doesn't make a pointer an array.)

You can do this:

   char s[] = {'a', 'b', 'c', '\0'};
// ^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^
// array      valid initializer for char[]

But not this:

   char* s = {'a', 'b', 'c', '\0'};
// ^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^
// pointer   invalid initializer for char*

7 Comments

Yes, but "abc" is an array, and can be used to initialize a pointer. Your answer is correct, but there's more to it. See my answer.
{'a', 'b', 'c', '\0'} is not an array. I could initialize a struct A { int a, b, c, d; } with it just as well as I could initialize an array with it.
@JohannesSchaub-litb: In this context, {'a', 'b', 'c', '\0'} is not an array expression, but it is a valid initializer for an array. "abc" is a valid initializer for either an array or a pointer. {'a', 'b', 'c', '\0'} is only a valid initializer for an array. My answer explains why (or at least tries to).
@KeithThompson i don't see why {'a', 'b', 'c', '\0'} can't be a valid struct initializer, and I can't see how your answer conclusively can be used to show that it can't.
@JohannesSchaub-litb: {'a', 'b', 'c', '\0'} certainly can be a valid struct initializer. I don't see how you concluded that I said it can't. My point is that in this particular context both {...} and "..." are valid initializers for arrays, but only "..." is a valid initializer for a pointer.
|
3

You can code this:

 char s[] = { 'a', 'b', 'c', '\0` };

which is the same as

 char s[] = "abc";

However, string literals are actually read only (since in the text segment). So you should understand a string literal as a const char s[] (even if it is not exactly that, if you care precisely about the C standard). In particular coding "abc"[1] = 'X'; is undefined behavior (and would probably crash with a segmentation violation on Linux).

Recent compilers (e.g. Clang/LLVM 3.2 or GCC 4.8) would probably warn you if you enable all warnings e.g. with gcc -Wall

Of course, pointers and arrays are not the same in C (arrays can decay to pointers), as this answer explains.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.