Les compilateurs C intégrés autorisent void main () car il se peut qu'il n'y ait pas de système d'exploitation auquel donner un code de retour.
Jeanne Pindar
26
Comment une question comme celle-ci peut-elle être si souvent votée? Ce n'est vraiment pas si intéressant ... Je veux dire, que les chaînes sont des tableaux et les tableaux sont des pointeurs, c'est vraiment un vieux chapeau en C, n'est-ce pas?
Felix Dombek
64
@Felix, c'est une question écrite de manière concise qui aborde un point commun de confusion pour les nouveaux arrivants dans la langue. La SO n'est pas réservée aux experts - elle s'adresse également aux débutants, et des questions ciblées comme celle-ci sont bonnes pour renvoyer les débutants à l'avenir.
bdonlan
37
@Felix: Vous vous trompez. les tableaux ne sont pas des pointeurs
John Dibling
Réponses:
209
Ce que vous comparez, ce sont les deux adresses mémoire pour les différentes chaînes, qui sont stockées à des emplacements différents. Cela ressemble essentiellement à ceci:
if(0x00403064==0x002D316A)// Two memory locations{
printf("Yes, equal");}
Utilisez le code suivant pour comparer deux valeurs de chaîne:
En outre, "a" == "a"peut effectivement retourner true, en fonction de votre compilateur, qui peut combiner des chaînes égales au moment de la compilation en une seule pour économiser de l'espace.
Lorsque vous comparez deux valeurs de caractères (qui ne sont pas des pointeurs), il s'agit d'une comparaison numérique. Par exemple:
GCC a également les options -fmerge-constantset -fno-merge-constantspermet d'activer / désactiver la fusion de chaînes et de constantes à virgule flottante entre les unités de traduction, bien que sur certains GCC, il semble que la fusion constante soit toujours activée quelle que soit cette option.
Adam Rosenfield
2
Cela fonctionnerait si vous utilisez «a» au lieu de «a». Le premier est un caractère, qui est en fait une valeur numérique.
GolezTrol
@GolezTrol: en C, le littéral «a» est en fait de inttype. :-) De plus, les pointeurs ne doivent pas nécessairement être des valeurs numériques.
Bastien Léonard
intest numérique aussi, n'est-ce pas? Mais je pensais que les caractères étaient Byte. Int est de 4 octets. Les pointeurs eux-mêmes sont également des nombres entiers. Ils contiennent l'adresse d'un ensemble de données (des données qui ne doivent en effet pas être numériques).
GolezTrol
'a' == 'A' // not true... MySQL ne diffère pas.
Steven
52
Je suis un peu en retard à la fête, mais je vais quand même répondre; techniquement les mêmes bits, mais d'un peu point de vue différent (langage C ci-dessous):
En C, l'expression "a"désigne une chaîne littérale , qui est un tableau statique sans nom de const char, avec une longueur de deux - le tableau se compose de caractères 'a'et'\0' - le caractère nul de fin signale la fin de la chaîne.
Cependant, en C, de la même manière que vous ne pouvez pas passer des tableaux aux fonctions par valeur - ou leur attribuer des valeurs ( après l'initialisation ) - il n'y a pas d'opérateur surchargé ==pour les tableaux, il n'est donc pas possible de les comparer directement. Considérer
int a1[]={1,2,3};int a2[]={3,4,5};
a1 == a2 // is this meaningful? Yes and no; it *does* compare the arrays for// "identity", but not for their values. In this case the result// is always false, because the arrays (a1 and a2) are distinct objects
Si le ==ne compare pas les tableaux, que fait-il alors? En C, dans presque tous les contextes - y compris celui-ci - les tableaux se désintègrent en pointeurs (qui pointent vers le premier élément du tableau) - et comparer des pointeurs pour l'égalité fait ce que vous attendez. Si efficacement, en faisant cela
"a"=="a"
vous comparez en fait les adresses des premiers caractères dans deux tableaux sans nom . Selon le standard C, la comparaison peut donner soit vrai soit faux (c'est-à-dire 1 ou 0) - "a"s peut en fait désigner le même tableau ou deux tableaux totalement indépendants. En termes techniques, la valeur résultante n'est pas spécifiée , ce qui signifie que la comparaison est autorisée (c'est-à-dire que ce n'est pas un comportement indéfini ou une erreur de syntaxe), mais l'une ou l'autre des valeurs est valide et l'implémentation (votre compilateur) n'est pas requise pour documenter ce qui va réellement se passer.
Comme d'autres l'ont souligné, pour comparer des "chaînes c" (c'est-à-dire des chaînes terminées par un caractère nul), vous utilisez la fonction de commodité strcmptrouvée dans le fichier d'en-tête standard string.h. La fonction a une valeur de retour de 0pour des chaînes égales; il est considéré comme une bonne pratique de comparer explicitement la valeur de retour au 0lieu d'utiliser l'opérateur `! ´, c'est-à-dire
strcmp(str1, str2)==0// instead of !strcmp(str1, str2)
Il n'est pas précisé si ces tableaux sont distincts à condition que leurs éléments aient les valeurs appropriées .
Donc, dans ce cas, il n'est pas précisé si les deux "a"sont distincts. Un compilateur optimisé pourrait en conserver un seul "a"à l'emplacement en lecture seule et les deux références pourraient y faire référence.
Parce qu'il s'agit de 2 const char*pointeurs séparés , pas de valeurs réelles. Vous dites quelque chose comme 0x019181217 == 0x0089178216qui bien sûr renvoie NON
Les littéraux de chaîne ne sont pas des pointeurs, ce sont des tableaux. Cependant, ils se désintègrent en pointeurs de comparaison.
GManNickG
@Gman vrai, désolé de ne pas être vraiment clair à ce sujet, j'ai tendance à l'oublier :)
Antwan van Houdt
9
En termes simples, C n'a pas d'opérateur de comparaison de chaînes intégré. Il ne peut pas comparer les chaînes de cette façon.
Au lieu de cela, les chaînes sont comparées à l'aide de routines de bibliothèque standard telles que strcmp () ou en écrivant du code pour parcourir chaque caractère de la chaîne.
En C, une chaîne de texte entre guillemets renvoie un pointeur vers la chaîne. Votre exemple compare les pointeurs, et apparemment vos deux versions de la chaîne existent à des adresses différentes.
Mais il ne s'agit pas de comparer les chaînes elles-mêmes, comme vous semblez vous y attendre.
Pourquoi vous attendez-vous à ce que les chaînes soient alignées sur une limite de 4 octets? Ce ne sont pas des entiers. 2 est ce à quoi je m'attendrais (si le compilateur ne les fusionne pas), car chaque chaîne mesure deux octets, y compris le terminateur nul.
Sergei Tachenov
Un certain degré d'alignement peut, par exemple, permettre strcmpd'exécuter plusieurs octets à la fois. Certains compilateurs le font, d'autres non, certains ne le font que pour des chaînes plus longues que le minimum ...
zwol
@Zack: comment connaîtraient-ils la longueur de la chaîne avant de les comparer?
Joachim Sauer
Je voulais dire, certains compilateurs alignent des chaînes plus longues que le minimum.
zwol
1
Vous comparez deux adresses mémoire, donc le résultat ne sera pas toujours vrai. Avez-vous essayé if('a' == 'a'){...}?
Les caractères n'occupent qu'un octet, mais les littéraux de caractère, tels que 'a', sont en fait des entiers.
Spidey
0
Certains compilateurs ont l'option 'merge strings' que vous pouvez utiliser pour forcer toutes les chaînes constantes à avoir la même adresse. Si vous utilisiez cela, le "a" == "a"serait true.
" et il devrait être vrai " - Non. Il n'est pas spécifié si les littéraux de chaîne seront stockés dans le même emplacement mémoire. Lisez les autres réponses.
void main
??? Ew ...Réponses:
Ce que vous comparez, ce sont les deux adresses mémoire pour les différentes chaînes, qui sont stockées à des emplacements différents. Cela ressemble essentiellement à ceci:
Utilisez le code suivant pour comparer deux valeurs de chaîne:
En outre,
"a" == "a"
peut effectivement retourner true, en fonction de votre compilateur, qui peut combiner des chaînes égales au moment de la compilation en une seule pour économiser de l'espace.Lorsque vous comparez deux valeurs de caractères (qui ne sont pas des pointeurs), il s'agit d'une comparaison numérique. Par exemple:
la source
-fmerge-constants
et-fno-merge-constants
permet d'activer / désactiver la fusion de chaînes et de constantes à virgule flottante entre les unités de traduction, bien que sur certains GCC, il semble que la fusion constante soit toujours activée quelle que soit cette option.int
type. :-) De plus, les pointeurs ne doivent pas nécessairement être des valeurs numériques.int
est numérique aussi, n'est-ce pas? Mais je pensais que les caractères étaient Byte. Int est de 4 octets. Les pointeurs eux-mêmes sont également des nombres entiers. Ils contiennent l'adresse d'un ensemble de données (des données qui ne doivent en effet pas être numériques).'a' == 'A' // not true
... MySQL ne diffère pas.Je suis un peu en retard à la fête, mais je vais quand même répondre; techniquement les mêmes bits, mais d'un peu point de vue différent (langage C ci-dessous):
En C, l'expression
"a"
désigne une chaîne littérale , qui est un tableau statique sans nom deconst char
, avec une longueur de deux - le tableau se compose de caractères'a'
et'\0'
- le caractère nul de fin signale la fin de la chaîne.Cependant, en C, de la même manière que vous ne pouvez pas passer des tableaux aux fonctions par valeur - ou leur attribuer des valeurs ( après l'initialisation ) - il n'y a pas d'opérateur surchargé
==
pour les tableaux, il n'est donc pas possible de les comparer directement. ConsidérerSi le
==
ne compare pas les tableaux, que fait-il alors? En C, dans presque tous les contextes - y compris celui-ci - les tableaux se désintègrent en pointeurs (qui pointent vers le premier élément du tableau) - et comparer des pointeurs pour l'égalité fait ce que vous attendez. Si efficacement, en faisant celavous comparez en fait les adresses des premiers caractères dans deux tableaux sans nom . Selon le standard C, la comparaison peut donner soit vrai soit faux (c'est-à-dire 1 ou 0) -
"a"
s peut en fait désigner le même tableau ou deux tableaux totalement indépendants. En termes techniques, la valeur résultante n'est pas spécifiée , ce qui signifie que la comparaison est autorisée (c'est-à-dire que ce n'est pas un comportement indéfini ou une erreur de syntaxe), mais l'une ou l'autre des valeurs est valide et l'implémentation (votre compilateur) n'est pas requise pour documenter ce qui va réellement se passer.Comme d'autres l'ont souligné, pour comparer des "chaînes c" (c'est-à-dire des chaînes terminées par un caractère nul), vous utilisez la fonction de commodité
strcmp
trouvée dans le fichier d'en-tête standardstring.h
. La fonction a une valeur de retour de0
pour des chaînes égales; il est considéré comme une bonne pratique de comparer explicitement la valeur de retour au0
lieu d'utiliser l'opérateur `! ´, c'est-à-direla source
Selon C99 (section 6.4.5 / 6)
Donc, dans ce cas, il n'est pas précisé si les deux
"a"
sont distincts. Un compilateur optimisé pourrait en conserver un seul"a"
à l'emplacement en lecture seule et les deux références pourraient y faire référence.Découvrez la sortie sur gcc ici
la source
Parce qu'il s'agit de 2
const char*
pointeurs séparés , pas de valeurs réelles. Vous dites quelque chose comme0x019181217 == 0x0089178216
qui bien sûr renvoie NONUtiliser à la
strcmp()
place de==
la source
En termes simples, C n'a pas d'opérateur de comparaison de chaînes intégré. Il ne peut pas comparer les chaînes de cette façon.
Au lieu de cela, les chaînes sont comparées à l'aide de routines de bibliothèque standard telles que strcmp () ou en écrivant du code pour parcourir chaque caractère de la chaîne.
En C, une chaîne de texte entre guillemets renvoie un pointeur vers la chaîne. Votre exemple compare les pointeurs, et apparemment vos deux versions de la chaîne existent à des adresses différentes.
Mais il ne s'agit pas de comparer les chaînes elles-mêmes, comme vous semblez vous y attendre.
la source
Des pointeurs.
Le premier
"a"
est un pointeur vers une chaîne ASCII terminée par un zéro.Le second
"a"
est un pointeur vers une autre chaîne ASCII terminée par null.Si vous utilisez un compilateur 32 bits, je m'attendrais
"a"=="a"-4
. Je viens de l'essayer avec tcc / Win32, et j'obtiens"a"=="a"-2
. Tant pis...la source
strcmp
d'exécuter plusieurs octets à la fois. Certains compilateurs le font, d'autres non, certains ne le font que pour des chaînes plus longues que le minimum ...Vous comparez deux adresses mémoire, donc le résultat ne sera pas toujours vrai. Avez-vous essayé
if('a' == 'a'){...}
?la source
cette question ouvre une très bonne piste d'explication pour tous les débutants ....
laissez-moi également y contribuer .....
comme tout le monde l'a expliqué ci-dessus, pourquoi vous obtenez une telle sortie.
maintenant si vous voulez votre prog. Pour imprimer "oui égal" alors
soit utiliser
ou
n'utilisez pas "a" comme chaînes, utilisez-les comme caractères ....
en C les caractères sont un entier court de 1 octet .......
la source
'a'
, sont en fait des entiers.Certains compilateurs ont l'option 'merge strings' que vous pouvez utiliser pour forcer toutes les chaînes constantes à avoir la même adresse. Si vous utilisiez cela, le
"a" == "a"
seraittrue
.la source
si la comparaison entre les caractères est toujours entre guillemets simples, par exemple
et C ne peut pas prendre en charge la comparaison de chaînes comme
"abc" == "abc"
C'est fait avec
strcmp("abc","abc")
la source
Ce gars n'utilise pas de variables. Au lieu de cela, il utilise temporairement des tableaux de texte:
a
eta
. La raison pour laquellene fonctionne pas bien sûr, c'est que vous ne comparez pas les variables.
Si vous créez des variables comme:
alors tu pourrais comparer
text
avectext2
, et ça devrait être vraiVous ne devriez peut-être pas oublier d'utiliser
{
et}
=)la source