Según el estándar c++98 (sección 2.13.4) las cadenas literales tienen como propiedad que durante el análisis léxico del código fuente (la primera fase que realiza el compilador, convirtiendo texto de entrada a tokens y símbolos) se concatenarán cadenas adyacentes.
In translation phase 6 (2.1), adjacent narrow string literals are concatenated and adjacent wide string literals are concatenated.
Esto viene a decir que podemos partir nuestras cadenas en cualquier momento sin poner ningún signo de concatenación entre ellas, de esta forma:
const char s1* = "dum" "de" "dum"; const char s2* = "dum" "de" "dum" ; |
Lo cual viene realmente bien para formar código bien indentado y formateado, pues aunque también podemos usar “\” para saltar de línea, el texto a continuación no puede estar indentado pues significaría incluir esos espacios/tabuladores en la cadena que estamos definiendo. Y lo realmente interesante es que todo esto está en la propia definición del lenguaje, no es ninguna ayuda concreta del compilador, a los ojos del programa todas las siguientes definiciones son idénticas:
#include <string> #include <iostream> const char * cmp( const char *s1, const char *s2 ); int main() { const char * s1 = "My spoon is too big" "My spoon is TOO BIG" "I AM A BANANA"; const char * s2 = "My spoon is too big\ My spoon is TOO BIG\ I AM A BANANA"; const char * s3 = ( std::string("My spoon is too big") + std::string("My spoon is TOO BIG") + std::string("I AM A BANANA") ).c_str(); std::cout << "s1 and s2 are " << cmp( s1, s2 ) << std::endl; std::cout << "s1 and s3 are " << cmp( s1, s3 ) << std::endl; std::cout << "s2 and s3 are " << cmp( s2, s3 ) << std::endl; return 0; } const char * cmp( const char *s1, const char *s2 ); { while( *s1 && *s2 && *s1++ == *s2++ ); if ( ( *s1 != *s2 ) || ( *s1 || *s2 ) ) return "different"; return "equal"; } |
$ c++ const_char_declaration_sample.cpp && ./a.out s1 and s2 are equal s1 and s3 are equal s2 and s3 are equal |