2011-11-09 14 views
16

Resulta que char c[] = {"a"}; es completamente válido tanto en C++03 como en C++11.¿Por qué un inicializador que contiene una cadena literal es válido para inicializar una matriz `char`?

No me esperaba, porque es una matriz de char no de char const*, y esperaría que un inicializador de llaves requiera un tipo compatible para cada uno de sus "artículos". Tiene un artículo, y eso es un char const* no un char.

Entonces, ¿qué hace que esta inicialización sea válida? ¿Y hay una razón para que sea así?


mismo modo, char c[] = {"aa"}; recopila, y la impresión de c resultados en la salida "aa".

Me gustaría esperaba char c[]{"a"} sea válida en C++ 11, por supuesto, pero no es lo mismo! Del mismo modo, char c[] = {'a'} es obvio en ambos, como es char c[] = "a".

+0

¿Has probado 'char c [] = {" aa "};'? –

+0

@VJo: También válido. –

+0

¿Por qué esperas que no sea válido? No está muy claro lo que estás preguntando. Es válido porque no hay ninguna regla que lo prohíba. ¿Qué regla esperas prohibir? – jalf

Respuesta

3

Los tipos escalares también se pueden inicializar con llaves (como estructuras y matrices).

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

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

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

Y como literales de cadena se pueden asignar a char matriz de punteros y

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

Parece adecuado para permitir char arr[] = { "literal" }; también.

+0

¡Ajá! Creo que eso tiene sentido. ¿Entonces estaba colgando en el inicializador agregado, cuando realmente es escalar? (Si entiendes) ¿Estamos "viendo" lo literal como una especie de escalar? –

+0

Sí, al menos así es como creo que se originó. Pero no estoy en el comité estándar C :) Solo adivinando ... – Pieter

+0

Muy bien; ¡Gracias! –

5

Aunque puede no ser necesariamente intuitivo, simplemente es permitido; hay una regla distinta en ambos estándares:

[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.

No puedo explicar por qué el comité lo hizo de esta manera, sin embargo.

+0

Bueno, es un buen toque.Ahora puede escribir 'char a [] =" abc ";', 'char b [] = {" abc "};' y 'char c [] {" abc "};' ... –

+0

@KerrekSB: ¡No veo cómo eso es útil! –

+0

'No puedo explicar por qué el comité lo hizo de esta manera, sin embargo' Usted podría agregar eso a la pregunta, ya que aún no ha sido respondida. Probablemente, la mayoría de las respuestas diría' Porque el estándar lo dice' pero tal vez alguna buena respuesta sea buena. hasta lo que podría decir '¿por qué?' –

0

Supongo que es para la compatibilidad C? En realidad, el T x = { value of T }; se aplica a otros tipos de T también. En el estándar C99,

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.

No sé por qué C tiene esto.

+0

La trama se espesa. –

+0

En cuanto a su segunda oración, ¿qué quiere decir? 'int main() {int i = 3; int * ptr = & i; int x [] = {ptr}; } '->' error: conversión inválida de 'int *' a 'int'' (como se esperaba, y como inicialmente esperaba con 'char' ... no es que el uso de un puntero aquí sea todo lo equivalente a un literal de todos modos, pero ya sabes lo que quiero decir ... estoy bastante seguro de que es un caso especial para "char"). [editar: no importa; Acabo de darme cuenta de que toda la cita aclara lo que dijiste, precisamente. Hubiera dicho "tipos" en lugar de "tipos" :)] –

+0

@ TomalakGeret'kal: Solo quiero decir 'int * x = {ptr};'. Un puntero no se puede convertir implícitamente en una matriz. Y el literal de cadena es un tipo de matriz (§6.4.5). – kennytm

Cuestiones relacionadas