16

It turns out that char c[] = {"a"}; is completely valid in both C++03 and C++11.

I would not expect it to be, because it is an array of char not of char const*, and I would expect a brace-initialiser to require a compatible type for each of its "items". It has one item, and that's a char const* not a char.

So what makes this initialisation valid? And is there a rationale for it being so?


Similarly, char c[] = {"aa"}; compiles, and printing c results in the output "aa".

I would expect char c[]{"a"} to be valid in C++11, of course, but it's not the same! Similarly, char c[] = {'a'} is obvious in both, as is char c[] = "a".

5
  • Have you tried char c[] = {"aa"};? Commented Nov 9, 2011 at 11:55
  • Why do you expect it to be invalid? It's not really clear what you're asking. It's valid because there's no rule prohibiting it. Which rule would you expect to forbid it? Commented Nov 9, 2011 at 11:57
  • 3
    @jalf: I thought it was obvious enough that this is non-obvious syntax, since you're initialising an array of type A with an initialiser containing one "element" of a non-compatible type B. I added this into the question anyway for the discerning. Commented Nov 9, 2011 at 11:57
  • @Tomalak: yes, it's non-obvious syntax. My point is that there might be more than one non-obvious thing about it, and while I can certainly explain the part of it that I find non-obvious, I don't know if that's the same thing that puzzled you. Therefore, in order to properly answer your question, we need to know what it is about this code snippet that puzzled you Commented Nov 9, 2011 at 12:16
  • 1
    @jalf: Again, that there is a valid brace-initialiser consisting of a item of type B that does not convert to the target type A when I'm initialising a A[]. Commented Nov 9, 2011 at 12:18

3 Answers 3

5

Although it may not necessarily be intuitive, it simply is allowed; there's a distinct rule for it in both standards:

[2003: 8.5.2/1]: A char array (whether plain char, signed char, or unsigned char) can be initialized by a string-literal (optionally enclosed in braces); a wchar_t array can be initialized by a wide string-literal (optionally enclosed in braces); successive characters of the string-literal initialize the members of the array. [..]

[n3290: 8.5.2/1]: A char array (whether plain char, signed char, or unsigned char), char16_t array, char32_t array, or wchar_t array can be initialized by a narrow character literal, char16_t string literal, char32_t string literal, or wide string literal, respectively, or by an appropriately-typed string literal enclosed in braces. Successive characters of the value of the string literal initialize the elements of the array.

I can't explain why the committee made it this way, though.

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

4 Comments

Well, it's a nice touch. Now you can write char a[] = "abc";, char b[] = { "abc" };, and char c[] { "abc" };...
@KerrekSB: I don't see how that's useful!
I can't explain why the committee made it this way, though You could add that to the Question as that is still unanswered.Arguably,Most answers would say Because Standard says so but maybe perhaps some goody good answer comes up which might just tell why?
@Als: Not sure "why did the committee do it this way" is constructive; it's subjective at best. Still, others are welcome to post new answers with a different interpretation of "why"! :)
3

Scalar types can also be initialized using braces (just like structs and arrays).

struct S { int x, char c };
S s = {5, 'a'};

int arr[] = {5, 6, 7};

/* (my guess) out of consistency */
int z = { 4 };

And since string literals can be assigned to char array's and pointers

char arr[] = "literal";
char* ptr = "another";

It seems fitting to allow char arr[] = { "literal" }; too.

2 Comments

Aha! I think that makes sense. So I was getting hung up on the aggregate initialiser, when really it's a scalar one? (If you get my drift) We're "viewing" the literal as a kind of scalar?
Yes, at least that's how I think it originated. But I'm not on the C standard committee :) Just guessing...
0

I guess it's for C compatibility? Actually, the T x = { value of T }; applies to other types of T as well. In the C99 standard,

6.7.8/11: The initializer for a scalar shall be a single expression, optionally enclosed in braces.

6.7.8/14: An array of character type may be initialized by a character string literal, optionally enclosed in braces.

6.7.8/15: An array with element type compatible with wchar_t may be initialized by a wide string literal, optionally enclosed in braces.

I don't know why C has this though.

3 Comments

As for your second sentence, what do you mean? int main() { int i = 3; int* ptr = &i; int x[] = { ptr }; } -> error: invalid conversion from 'int*' to 'int' (as expected, and as I initially expected with char ... not that the use of a pointer here is all that equivalent to a literal anyway, but you know what I mean... I'm fairly sure it's a special case for char). [edit: never mind; just realised the entire quote clarifies what you said, precisely. I'd have said "kinds" rather than "types" :)]
@TomalakGeret'kal: I just mean int* x = { ptr };. A pointer cannot be implicitly converted to an array. And string literal is an array type (§6.4.5).
I know a string literal is an array type hence "not that the use of a pointer here is all that equivalent to a literal anyway" :P

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.