Je suis curieux de ce code:
cout << 'test'; // Note the single quotes.
me donne une sortie de 1952805748
.
Ma question: la sortie est-elle une adresse en mémoire ou quelque chose?
Je suis curieux de ce code:
cout << 'test'; // Note the single quotes.
me donne une sortie de 1952805748
.
Ma question: la sortie est-elle une adresse en mémoire ou quelque chose?
Réponses:
C'est un littéral à plusieurs caractères. 1952805748
est 0x74657374
, qui se décompose en
0x74 -> 't'
0x65 -> 'e'
0x73 -> 's'
0x74 -> 't'
Éditer:
Norme C ++, §2.14.3 / 1 - Littéraux de caractères
(...) Un littéral de caractère ordinaire qui contient plus d'un caractère C est un littéral multicaractère. Un littéral multicaractère a un type int et une valeur définie par l'implémentation.
sizeof(int)
implémentation est également définie. Ainsi, non seulement l'implémentation de l'ordre de stockage est définie, mais la longueur maximale de ceux-ci l'est également.
Non, ce n'est pas une adresse. C'est le soi-disant caractère multi-octets.
Il s'agit généralement des valeurs ASCII des quatre caractères combinés.
't' == 0x74; 'e' == 0x65; 's' == 0x73; 't' == 0x74;
Donc, 0x74657374 est 1952805748.
Mais il peut également s'agir de 0x74736574 sur un autre compilateur. Les normes C et C ++ indiquent que la valeur des caractères multi-octets est définie par l'implémentation . Donc, généralement, son utilisation est fortement déconseillée.
int
y a 4 octets sur la plupart des machines, je ne pense pas qu'il soit logique d'utiliser plus de 4 octets. Oui, il était destiné à être un moyen pratique d'écrire certaines constantes, mais malheureusement, différents compilateurs l'ont interprété différemment, donc de nos jours la plupart des styles de codage découragent son utilisation.
==
vérifier
Un littéral de caractère ordinaire qui contient plusieurs caractères C est un littéral multicaractère. Un littéral multicaractère a un type int et une valeur définie par l'implémentation.
Le comportement défini par l'implémentation doit être documenté par l'implémentation. par exemple dans gcc vous pouvez le trouver ici
Le compilateur évalue une constante de caractère à plusieurs caractères un caractère à la fois, décalant la valeur précédente laissée par le nombre de bits par caractère cible, puis -ou dans le modèle binaire du nouveau caractère tronqué à la largeur d'une cible personnage. Le motif binaire final est donné de type int et est donc signé, que les caractères individuels soient signés ou non.
Consultez l'explication de cette page pour plus de détails
Ce sont vraiment des int
s. Ils sont largement utilisés dans les énumérations de l'API Core Audio, par exemple, dans le CoreAudioTypes.h
fichier d' en- tête,
enum
{
kAudioFormatLinearPCM = 'lpcm',
kAudioFormatAC3 = 'ac-3',
kAudioFormat60958AC3 = 'cac3',
kAudioFormatAppleIMA4 = 'ima4',
kAudioFormatMPEG4AAC = 'aac ',
kAudioFormatMPEG4CELP = 'celp',
} ;
Il y a beaucoup de bavardages à propos de ce qui n'est pas "indépendant de la plate-forme", mais lorsque vous utilisez une API conçue pour une plate-forme spécifique, qui se soucie de la portabilité. La vérification de l'égalité sur la même plate-forme n'échouera jamais. Ces enum
valeurs sont plus faciles à lire et contiennent en fait leur identité dans leur valeur , ce qui est plutôt agréable.
Ce que j'ai essayé de faire ci-dessous est d'envelopper un littéral de caractères multi-octets pour qu'il puisse être imprimé (sur Mac, cela fonctionne). Ce qui est étrange, c'est que si vous n'utilisez pas les 4 caractères, le résultat devient faux ci-dessous.
#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;
}
Ce type de fonctionnalité est vraiment bon lorsque vous construisez des analyseurs. Considère ceci:
byte* buffer = ...;
if(*(int*)buffer == 'GET ')
invoke_get_method(buffer+4);
Ce code ne fonctionnera probablement que sur un endianess spécifique et pourrait traverser différents compilateurs