2011-09-18 38 views
259

Tengo curiosidad acerca de este código:¿Qué hacen las comillas simples en C++ cuando se usan en varios caracteres?

cout << 'test'; // Note the single quotes. 

me da una salida de 1952805748.

Mi pregunta: ¿El resultado es una dirección en la memoria o algo así?

+52

Niza primera cuestión en StackOverflow. –

+10

Preste atención a que el valor real es la implementación definida http://stackoverflow.com/questions/3960954/c-multicharacter-literal – FireAphis

+17

Niza última pregunta en StackOverflow. :( –

Respuesta

276

Es un literal de varios caracteres. 1952805748 es 0x74657374, que se descompone como

0x74 -> 't' 
0x65 -> 'e' 
0x73 -> 's' 
0x74 -> 't' 

Editar:

C++ estándar, §2.14.3/1 - caracteres literales

(...) un literal de carácter ordinario que contiene más de un c-char es un literal de múltiples caracteres. Un literal de múltiples caracteres tiene el tipo int y el valor definido por la implementación.

+9

No mencionó que esta es la implementación definida. –

+2

Supongo que lo más divertido de esa definición es que 'sizeof (int)' también se define como implementación. La implementación de la orden de almacenamiento está definida, pero la longitud máxima de estos también lo es. – bobobobo

69

No, no es una dirección. Es el llamado personaje multibyte.

Normalmente, son los valores ASCII de los cuatro caracteres combinados.

't' == 0x74; 'e' == 0x65; 's' == 0x73; 't' == 0x74; 

Así 0x74657374 es 1952805748.

Pero también puede haber 0x74736574 en algún otro compilador. Los estándares C y C++ dicen que el valor de los caracteres multibyte es implementación definida. Por lo tanto, generalmente su uso es fuertemente desaconsejado.

+0

¿La longitud de dicho carácter multibyte está restringida a 4 bytes? Es decir, representa una int escrita como caracteres? – Giorgio

+2

@Giorgio: solo el estándar dice que es implementación definida, sin más detalles. En la práctica, dado que 'int' tiene 4 bytes en la mayoría de las máquinas, no creo que tenga sentido usar más de 4 bytes. Sí, estaba destinado a ser una forma conveniente de escribe algunas constantes, pero lamentablemente diferentes compiladores lo han interpretado de manera diferente, por lo que hoy en día la mayoría de los estilos de codificación desalientan su uso. – chys

+2

@chys: Y el hecho de que esté definido por la implementación significa que ni siquiera se requiere que sea consistente. Un compilador conforme podría dar a todos los literales de múltiples caracteres el valor 0, por ejemplo (aunque eso sería desagradable). –

17

Un literal de carácter ordinario que contiene más de un c-char es un literal de múltiples caracteres. Un literal de múltiples caracteres tiene un tipo int y un valor definido por la implementación.

La implementación del comportamiento definido se debe documentar por la implementación. por ejemplo, en gcc se puede encontrar here

El compilador valora un carácter multi-carácter constante un carácter a la vez, cambiando el valor anterior dejó por el número de bits por carácter objetivo, y luego o-ción en el patrón de bits del nuevo carácter truncado con el ancho de un personaje objetivo. El patrón de bits final tiene el tipo int y, por lo tanto, está firmado, independientemente de si los caracteres individuales están firmados o no .

Comprobar la explicación en this page para más detalles

10

Son realmente sólo int s.Se utilizan ampliamente en la API de Core Audio de enumeración por ejemplo, en el archivo CoreAudioTypes.h cabecera,

enum 
{ 
    kAudioFormatLinearPCM    = 'lpcm', 
    kAudioFormatAC3      = 'ac-3', 
    kAudioFormat60958AC3    = 'cac3', 
    kAudioFormatAppleIMA4    = 'ima4', 
    kAudioFormatMPEG4AAC    = 'aac ', 
    kAudioFormatMPEG4CELP    = 'celp', 
} ; 

Hay mucha charla sobre esto no ser "independiente de la plataforma", pero cuando se está utilizando una API que es hecho para una plataforma específica, que se preocupa por la portabilidad. Verificar la igualdad en la misma plataforma nunca fallará. Estos valores enum 'd son más fáciles de leer y en realidad contienen su identidad en su valor, lo cual es bastante agradable.

Lo que he tratado de hacer a continuación es envolver un carácter multibyte literal para que se pueda imprimir (en Mac esto funciona). Lo extraño es que, si no se utiliza encima de los 4 caracteres, el resultado se vuelve incorrecta a continuación ..

#include <stdio.h> 

#define MASK(x,BYTEX) ((x&(0xff<<8*BYTEX))>>(8*BYTEX)) 

struct Multibyte 
{ 
    union{ 
    int val ; 
    char vals[4]; 
    }; 

    Multibyte() : val(0) { } 
    Multibyte(int in) 
    { 
    vals[0] = MASK(in,3); 
    vals[1] = MASK(in,2); 
    vals[2] = MASK(in,1); 
    vals[3] = MASK(in,0); 
    } 
    char operator[](int i) { 
    return val >> (3-i)*8 ; // works on mac 
    //return val>>i*8 ; // might work on other systems 
    } 

    void println() 
    { 
    for(int i = 0 ; i < 4 ; i++) 
     putc(vals[i], stdout) ; 
    puts("") ; 
    } 
} ; 

int main(int argc, const char * argv[]) 
{ 
    Multibyte('abcd').println() ; 
    Multibyte('x097').println() ; 
    Multibyte('\"\\\'\'').println() ; 
    Multibyte('/*|').println() ; 
    Multibyte('d').println() ; 

    return 0; 
} 
+3

_ "La comprobación de la igualdad en la misma plataforma nunca fallará." _ Podría. Actualiza a Visual Studio _xyz_ y muerde tu lengua. Esta biblioteca ha tomado una decisión _terrible_. –

+0

@LightnessRacesinOrbit * "Actualiza a Visual Studio xyz y muerde tu lengua." * Core Audio API es la API de audio del sistema de OS X, por lo que no es relevante. –

+2

@ Jean-MichaëlCelerier: Bien; actualiza tu versión de OSX Clang y muerde tu lengua ... –

0

Este tipo de característica es muy bueno cuando se está construyendo analizadores. Considere esto:

byte* buffer = ...; 
if(*(int*)buffer == 'GET ') 
    invoke_get_method(buffer+4); 

Este código es probable que sólo trabajar en endianess específico y se puede romper a través de diferentes compiladores

Cuestiones relacionadas