2010-07-09 16 views
5

Supongamos que he siguiente inicialización de una matriz de caracteres:inicializar arrays de char de una manera similar a la inicialización de los literales de cadena

char charArray[]={'h','e','l','l','o',' ','w','o','r','l','d'}; 

y también tengo tras la inicialización de una cadena literal:

char stringLiteral[]="hello world"; 

La única diferencia entre los contenidos de la primera matriz y la segunda cadena es que la segunda cadena tiene un carácter nulo en su extremo.

Cuando se trata de inicializar una matriz de caracteres, ¿hay una macro o algo que nos permita poner nuestro texto de inicialización entre dos comillas dobles pero donde la matriz no obtiene un carácter de terminación nulo adicional?

Simplemente no tiene sentido para mí que cuando no se necesita un carácter nulo de terminación, debemos usar la sintaxis de la primera inicialización mencionada y escribir dos comillas simples para cada carácter en el texto del inicializador, así como las marcas de virulencia para separar personajes.

Debo añadir que cuando quiero tener una matriz char, también debería ser obvio que no quiero usarla con funciones que dependen de cadenas literales junto con el hecho de que ninguna de las funciones en las que se utiliza una cadena resultados literales, es en mi consideración.

Estoy agradecido por sus respuestas.

+0

@Michael - es un requisito en los estándares C y C++. – Steve314

+1

El * PROBLEMA * que enfrenta es que el lenguaje requiere que "cadenas entrecomilladas" terminen en NUL. – torak

Respuesta

0

que podría haber encontrado una manera de hacer lo que quiera, aunque no es directamente lo que quería, pero es probable que tenga el mismo efecto.
en primer lugar considerar dos clases siguientes:

template <size_t size> 
class Cont{ 
public: 
    char charArray[size]; 
}; 
template <size_t size> 
class ArrayToUse{ 
public: 
    Cont<size> container; 
    inline ArrayToUse(const Cont<size+1> & input):container(reinterpret_cast<const Cont<size> &>(input)){} 
}; 

Antes de continuar, es posible que desee ir here y echar un vistazo a los constructores de expresión constantes y tipos de inicialización.
Ahora mira siguiente código:

const Cont<12> container={"hello world"}; 
ArrayToUse<11> temp(container); 
char (&charArray)[11]=temp.container.charArray; 

texto Finalmente inicializador está escrito entre dos comillas dobles.

+0

Asegúrate de salpicar algunos comentarios sobre ese constructo. Como ya habrás adivinado por otras respuestas y comentarios, ** no ** tener una terminación '\ 0' es un concepto bastante inusual y debe venir con las señales de advertencia apropiadas. – DevSolar

+0

@DevSolar: apreciado – Pooria

3

No hay forma de hacer lo que quiera. La primera forma de inicializar la matriz especifica inicializadores separados para cada carácter, lo que permite dejar explícitamente el '\ 0'. El segundo es inicializar una matriz de caracteres a partir de una cadena de caracteres, que en C/C++ siempre termina con un carácter nulo.

EDIT: corregido: 'carácter puntero' -> 'array de caracteres'

+2

En realidad, no creo que el segundo caso sea inicializar un puntero a una cadena de caracteres. Está creando una matriz e inicializando sus contenidos en función del contenido de la cadena. Y sí, la diferencia realmente importa. – torak

+0

nunca noté el concepto de "inicializadores de caracteres separados", gracias – Pooria

0

La respuesta básica es que la gran mayoría de los arrays de char son cadenas - en C, las cadenas se termine con un nulo. C++ heredó esa convención. Incluso cuando ese nulo no es necesario, la mayoría de las veces no es un problema simplemente dejarlo allí de todos modos.

Las macros no son lo suficientemente potentes para hacer lo que desea. Las plantillas serían, excepto que no tienen ningún manejo de cadenas en tiempo de compilación.

Normalmente, cuando la gente quiere mezclar bytes numéricos y literales de cadenas en la misma secuencia char-array, usan un literal de cadena pero usan escapes de caracteres hexadecimales como \xFF.

6

está permitido en C para declarar la matriz de la siguiente manera, que inicializarlo sin copiar el '\0' terminación

char c[3] = "foo"; 

Pero es ilegal en C++. No conozco un truco que lo permita para C++. El estándar C++ dice además

Justificación: Cuando estas matrices no terminadas son manipuladas por rutinas de cadena estándar, existe la posibilidad de una gran catástrofe.
Efecto en la función original: Eliminación de la característica semánticamente bien definida.
Dificultad de conversión: Transformación semántica. Las matrices deben declararse como un elemento más grande para contener la cadena que termina '\ 0'.
How ampliamente utilizado: Raramente. Este estilo de inicialización de matriz se ve como un pobre estilo de codificación.

+1

. Su respuesta me resulta un poco confusa. 'char c [4] =" foo ";' pone el carácter nulo en su lugar? ¿Sigue siendo este el pobre estilo de codificación al que se hace referencia? ¿Qué tal 'char [128] =" ";'? ¿Solo inicializando un buffer? ¿Esta todo bien? ¿O es 'char [128] = {'\ 0'}; 'mejor? – nus

+0

De acuerdo con el libro de referencia de Randal Albert, 'char c [4] =" foo ";' coloca un carácter nulo para usted y de acuerdo con el libro, se recomienda escribirlo como 'char [4] =" foo " ; '. 'char c [3] =" foo ";' es ilegal porque necesitamos reservar un espacio para el carácter nulo de terminación en la parte posterior. – user3437460

+0

@user vale la pena leer toda mi respuesta que dice "Las matrices deben declararse como un elemento más grande para contener la cadena que termina '\ 0'." –

0

litb has the technically correct answer.

En cuanto a una opinión, digo simplemente vivir con el 'desperdicio' del extra '\ 0'. Muchos errores son el resultado de un código que espera un nulo de terminación donde uno no está (este consejo puede parecer ir directamente en contra de algún otro consejo que di hace un día o dos sobre no molestarme con poner a cero un búfer completo. Yo reclamo que no hay contradicción: todavía abogaba por la terminación nula de la cadena en el búfer).

Si realmente no puede vivir con el terminador '\ 0' debido a alguna semántica en la estructura de datos que está tratando, como puede ser parte de una estructura empaquetada más grande, siempre puede iniciar la matriz usted mismo (que creo que debe haber menos eficiente que lo que el compilador podría haber hecho para usted):

#define MY_STRING_LITERAL "hello world" 

char stringLiteral[sizeof(MY_STRING_LITERAL) - 1]; 

memcpy(stringLiteral, MY_STRING_LITERAL, sizeof(stringLiteral)); 
+0

Creo que su método debe ser tan eficiente como el del compilador para las matrices con clase de almacenamiento automático, pero para las matrices con clase de almacenamiento estático o las de alcance global, creo que no hay copia en tiempo de ejecución realizada por el compilador. – Pooria

+0

@ garrett2011: eso es cierto para los elementos 'const char []', pero creo que la mayoría de las matrices no const tendrán sus valores iniciales copiados de la imagen del programa 'text' (que no se puede escribir en la mayoría de las plataformas) en RAM antes de invocar 'main()'. Siempre que el 'memcpy()' se realice solo una vez, en lo que se refiere a la eficiencia, es aproximadamente seis de una, media docena de la otra, ya sea que lo haga el tiempo de ejecución o su código. –

Cuestiones relacionadas