4

I've got a question about initializing char pointers vs other data type pointers. Specifically, we are allowed to initialize char pointers as follows:

char *char_ptr = "Hello World";

As far as I know, the only thing special about a string is that it is a '0' terminated character array. However, we are not allowed to do the following:

int *int_ptr = {1,2,3,4};

but we must do this:

int int_arr[] = {1,2,3,4};
int_ptr = int_arr;

in order to let int_ptr point to the first element of int_array.

In the char case, we have not explicitly defined the string "Hello World" as a char array before letting char_ptr point to the string, but have initialized the char_ptr directly using the string "Hello World".

My question is, why is this the case, what is special about strings that allows us to do this but can't do so with other types?

Thanks in advance,

Sriram

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • 2
    btw in C++ it's better to write `const char * char_ptr = "string literal"`, conversion to `char*` is deprecated – RiaD Jan 12 '13 at 16:12
  • 2
    @RiaD, It's still better to write that in C. You can't modify string literals there either. – chris Jan 12 '13 at 16:12

5 Answers5

3

You can do the same in C99 or later for other types using compund literals:

#include <stdio.h>

int main(void) {
    int *ptr = (int[]){ 1, 2, 3, 4 };
    for(int i = 0; i < 4; ++i) {
        printf("%d: %d\n",i, ptr[i]);
    }
    return 0;
}

The compound literal (int[]){ 1, 2, 3, 4 } creates an unnamed int[4], just like "Hello" creates an unnamed char[6].

So as of C99, char is only special in providing a more convenient syntax.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • this seems to work with one small tweak: const is required since by itself (int []){1,2,3,4} does not have a fixed memory. The following version works: const int *ptr = (const int []){1,2,3,4} -- thanks for your help -- sn – Sriram Nagaraj Jan 12 '13 at 16:46
  • Compiles without warnings and works as C99. Neither my g++ nor my clang++ spit out a warning either, and it works [though I didn't know C++ had compund literals, so the latter surprises me a little]. – Daniel Fischer Jan 12 '13 at 16:51
1

The answer is:

Strings(literals) are treated as special.

Believe it! Accept it, and Live with it.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

It is because string are used so much that there's an easier way to define them made available. It's way easier than making explicitly an array of character every time.

Arnaud
  • 410
  • 5
  • 10
1

"Hello World" is a string literal. It has type "array of 12 const char" and static storage duration. That is, it gives you an array in memory that lasts for the duration of your program. It has 12 char because of the null character, which you correctly point out. Now lets consider the two cases.

With const char *char_ptr = "Hello World"; you are relying on the fact that an array can be converted to a pointer to its first element. So your char_ptr points to the first element of the static data that the literal represents.

With const char char_arr[] = "Hello World";, what happens is a special rule for initializing arrays of characters. What you get is char_arr which is of type "array of 12 const char" again, but the characters from the static string data are used to initialize each element in the array (§8.5.2). That means, your array char_arr is a copy of the static string data.

When we do int *int_ptr = {1,2,3,4}; we get an error. Why? Because {1, 2, 3, 4} isn't like the string literal above. {1, 2, 3, 4} is an initializer, not a literal at all. In fact, it's an initializer list and can only be used to initialize things. It is not a literal. It does not create some static array with the values 1, 2, 3, and 4 in it and then give you a pointer. It is simply used to directly initialize an array. So what would your int_ptr point to? The array does not exist anywhere for it to point to.

However, int int_arr[] = {1,2,3,4}; is the correct use of this initializer list. You get an array, int_arr, where each of the elements are initialized to the elements in the initializer list.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • String literals have type pointer to `char`, and those `char` are not even `const`. – effeffe Jan 12 '13 at 16:20
  • @effeffe §2.14.5: "A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration" – Joseph Mansfield Jan 12 '13 at 16:21
  • So in summary, string literals are special. – Alok Save Jan 12 '13 at 16:21
  • @AlokSave I wouldn't say that. I'd say they're special compared to other literals, yes, because they behave slightly differently. However, we're comparing a string literal to an initializer list. These are two completely separate concepts. There is just an alternative form of initialization for character arrays that involves string literals. I suppose it would be better to say "initialization of a character array" is special. – Joseph Mansfield Jan 12 '13 at 16:22
  • Sorry, you're right about the pointer, apologies. But characters are not const-qualified in C (probably C++ is different about this): *"For character string literals, the array elements have type char"*. I can't find your quote in the standard, so I think you're talking about C++. http://stackoverflow.com/q/2245664/1202636 – effeffe Jan 12 '13 at 16:35
0

When you set char *char_ptr = "Hello World", you are setting the address of the string literal to char_ptr. But, in case of other data types, there is nothing analogous to string literals. So, it is not allowed.

Jay
  • 24,173
  • 25
  • 93
  • 141