Estou curioso sobre este código:
cout << 'test'; // Note the single quotes.
me dá uma saída de 1952805748
.
Minha pergunta: a saída é um endereço na memória ou algo assim?
Estou curioso sobre este código:
cout << 'test'; // Note the single quotes.
me dá uma saída de 1952805748
.
Minha pergunta: a saída é um endereço na memória ou algo assim?
Respostas:
É um literal com vários caracteres. 1952805748
é 0x74657374
, que se decompõe como
0x74 -> 't'
0x65 -> 'e'
0x73 -> 's'
0x74 -> 't'
Editar:
Padrão C ++, §2.14.3 / 1 - Literais de caracteres
(...) Um literal de caractere comum que contém mais de um c-char é um literal de vários caracteres. Um literal de vários caracteres possui o tipo int e o valor definido pela implementação.
sizeof(int)
implementação é definida também. Portanto, não apenas a implementação da ordem de armazenamento é definida, mas também o comprimento máximo deles.
Não, não é um endereço. É o chamado caractere multibyte.
Normalmente, são os valores ASCII dos quatro caracteres combinados.
't' == 0x74; 'e' == 0x65; 's' == 0x73; 't' == 0x74;
Então 0x74657374 é 1952805748.
Mas também pode ser 0x74736574 em algum outro compilador. Os padrões C e C ++ dizem que o valor dos caracteres multibyte é definido pela implementação . Portanto, geralmente seu uso é fortemente desencorajado.
int
são 4 bytes na maioria das máquinas, não acho que faça sentido usar mais de 4 bytes. Sim, ele pretendia ser uma maneira conveniente de escrever algumas constantes, mas, infelizmente, diferentes compiladores a interpretaram de maneira diferente; portanto, hoje em dia a maioria dos estilos de codificação desencoraja seu uso.
==
deve verificar
Um literal de caractere comum que contém mais de um c-char é um literal de vários caracteres. Um literal de vários caracteres possui o tipo int e o valor definido pela implementação.
É necessário que o comportamento definido da implementação seja documentado pela implementação. por exemplo, no gcc, você pode encontrá-lo aqui
O compilador valoriza um caractere de vários caracteres, constante um caractere de cada vez, alterando o valor anterior deixado pelo número de bits por caractere de destino e, em seguida, inserindo o padrão de bits do novo caractere truncado para a largura de um destino personagem. O padrão de bits final recebe o tipo int e, portanto, é assinado, independentemente de caracteres únicos serem assinados ou não.
Verifique a explicação nesta página para mais detalhes
Eles são realmente apenas int
s. Eles são usados extensivamente nas enum da API de áudio principal, por exemplo, no CoreAudioTypes.h
arquivo de cabeçalho,
enum
{
kAudioFormatLinearPCM = 'lpcm',
kAudioFormatAC3 = 'ac-3',
kAudioFormat60958AC3 = 'cac3',
kAudioFormatAppleIMA4 = 'ima4',
kAudioFormatMPEG4AAC = 'aac ',
kAudioFormatMPEG4CELP = 'celp',
} ;
Há muita conversa sobre isso não ser "independente de plataforma", mas quando você usa uma API feita para uma plataforma específica, que se preocupa com a portabilidade. A verificação da igualdade na mesma plataforma nunca falha. Esses enum
valores são mais fáceis de ler e, na verdade, contêm sua identidade em seu valor , o que é bastante bom.
O que tentei fazer abaixo é agrupar literalmente um caractere multibyte para que possa ser impresso (no Mac, isso funciona). O estranho é que, se você não usar todos os 4 caracteres, o resultado ficará errado abaixo ..
#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;
}
Esse tipo de recurso é realmente bom quando você está construindo analisadores. Considere isto:
byte* buffer = ...;
if(*(int*)buffer == 'GET ')
invoke_get_method(buffer+4);
Esse código provavelmente funcionará apenas em endianess específico e pode ser dividido em diferentes compiladores