3
  1. char *s = "Hello"
  2. char s[6] = "Hello"

Any one of the above syntax would work fine.

But what about following?

  1. int a[3] = {1,2,3} (this would work excellent)
  2. But why not this, int *a = {1, 2, 3};?

Explanation along with the comparison between case [2] and [4] will be helpful.

1
  • Note that actually case 1 is the exception, not the others. Also note that expecially for C it is often better to have an additional level of checking for the compiler, as you can easily create rather complex expressions where only experts will deduce the semantics easily. Commented May 26, 2015 at 14:45

7 Answers 7

5

Reason why that will not work is that the data type of the initialier is not defined. For the string literal, this is given implicitly by the syntax. But { 1,2,3} could be an array, a struct, or many other variants.

You have to specify the type:

int *ia = (int []){1,2,3};

This uses a compound literal (C99).

Note this not only works for initialization, but also in normal code.

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

2 Comments

and can you specifically give me examples of "many other variants"?
@ravipandhi: struct with anonymous union, array of floats relying on coercion? That enough? Use your imagination.
5

It's because "Hello" is replaced with "The address of the string literal Hello". So char *s = "Hello" means "Assign to the pointer s the address of the string literal Hello".

Meanwhile {1, 2, 3} does not constitute an address and is not replaced. You can't assign anything else but an address to a pointer, so you can't write int *a = {1, 2, 3}.

Comments

3
  1. char *s="Hello"

    Here, s is a pointer to char, which points to the base address of the string literal "Hello".

  2. char s[6]="Hello"

    here s is an array of 6 chars, having H, e, l, l, o and \0 as initilizer value.

  3. int a[3]={1,2,3}

    here, a is an int array of 3 elements, initialized with the values 1, 2 and 3.

Note: all the above three are legal and valid.

  1. int *a={1,2,3}; is invalid.

    here, a is of type int *, and the brace enclosed list does not supply a value of int *. So, this is not a defined behaviour and invalid.

6 Comments

if 's' points to the base address of character array "Hello", then why does 'a' not point to the base address of integer array {1,2,3} ? Something special, here?
@ravipandhi yes, "Hello" is called a string literal, which returns the base address of the literal. {1,2,3} is not an int lireal, it's called breace enclosed initalizer list.
just as s++ traverses to the next element in the character array by adding 1 byte(size of char) to the base, doesnt case 4 seem to be logically correct like "a++ traverses to the next element in the integer array by adding machine dependent integer size to the base?
@ravipandhi understand the basic issue here, "Hello" returns a char * which you can put into another char *, but {1,2,3} does not return an int *, in the first place.
@ravipandhi: That's just how the language was designed. String literals are special, and are treated differently from initializers like {1, 2, 3}. A string literal like "Hello" is an array expression, and under most circumstances array expressions "decay" to pointer expressions. The initializer {1,2,3}, by itself, is not an array expression because the language defintion says so. As Yu Hao points out below, (int[]){1,2,3} is an array expression (as of C99), which decays to a pointer expression, so you could write int *a = (int[]){1,2,3}. .
|
3

The reason for case 4 not being supported but the other cases being supported are historical. The factors are lobbying and political interplay between some early influential programmers and compiler vendors, rather than a deliberate reasoned technical decision.

So, if you're looking for a robust technical justification, you won't find one.

Historically, cases 2 and 3 have been supported since quite early in the evolution of C. Your case 2 achieves the same effect as

  char s[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

There is no counterpart of string literals to initialise arrays of anything other than char types.

Historically, case 1 is an anomaly introduced by programmers who wanted to achieve the effect of

  char s_temp[] = "Hello";
  char *s = temp_s;

with less typing (i.e. as a single statement). The lobbying for support of case 1 eventually won out (it was introduced into mainstream compilers, and later into the standard). Case 1 is the only case in the standard where a pointer can be initialised directly using an array initialiser without any need for a type conversion.

Historically, there has never been demand or lobbying from programmers for case 4.

Which, like it or not, is the reason why case 1,2,3 are supported but case 4 is not.

There is no real comparison between cases 2 and 4, because they (seek to) achieve different things. A string literal, as in case 2, is an array initialiser that only works for arrays of char - there is no counterpart for non-char types. Case 4 is trying to initialise a pointer using an array initialiser.

7 Comments

Thats quite an explanation, so the programmers never wanted something like case 4, so it doesnt exist? Can they provide support for it like "the case 4 wants to initialise an int array and the next int to be found is by adding the size of integer in the base address? Is this possible?
From a compiler's view there are actually good reasons not to support this. It might have become just too complicated for the compiler to deduce the actual type. With C99' compound literals, a superiour (as being more explicit and general) alternaitve has been introduced.
@Olaf Well, it was getting too complicated to support this in the past? With C99, they came up with a solution of typecasting to the specific type to provide support ? Is it? then the question is solved! :)
@ravipandhi: Don't be a smartass. That is not a typecast, but a compound literal. A cast will convert/force reinterpretation of on type to another, while the braces on a compound initializer tells the compiler the actual type. You have to look at the whole construct: parenthesized type plus block, not just the first part. A typecast would not make sense on a block actually. And, yes, it is quite a difference if the compiler has to deduce the type from the left side or if it is already presented on the right side as for any other expression. As Peter wrote, actually `char *cp = "" is the hack
Also note we are talking about compilers in the 80ies; they had enough to do trying to optimize code, so were quite happy having less parsing effort and memory footprint.
|
2
int *a = {1, 2, 3};

is syntactically incorect because {1, 2, 3} cannot be used to initialize a pointer.

However, a little modification could make it work:

int *a = (int []){1, 2, 3};

It's a C99 compound literal.

Comments

1

Initializing a character array with a string is a special case: char s[6] = "hello" is treated as if the code were written char s[6] = { 'h', 'e', 'l', 'l', 'o', '\0'};. Initializing a character array with a string is a common occurrence, so this idiom makes sense.

4 Comments

This does not answer the question, IMO.
Does writing char s[6] = { 'h', 'e', 'l', 'l', 'o', '\0'}; make it writeable? I would think so.
@Eregrith, yes. s is a local array and the manner in which it is initialized does not change its mutability.
@WilliamPursell Ah yes sorry I forgot char s[6] = "hello" is also writeable. My bad
0
  1. int a[3] = {1,2,3};

This is the normal initialization syntax for arrays.

  1. char s[6] = "Hello";

This is a special case initialization syntax only for character arrays, where you can write a string literal on the right side and it will expand out to the normal initialization syntax as above, i.e. char s[6] = {'H','e','l','l','o','\0'};

  1. char *s = "Hello";

This is the normal initialization syntax for a scalar variable, initialized to an expression on the right side. Here, "Hello" is a valid C expression.

  1. int *a = {1, 2, 3};

This is different from (1) above in that {1, 2, 3} is not a valid C expression.

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.