Je suis un peu confus à propos de quelque chose. J'avais l'impression que la manière correcte de lire une corde en C scanf()
allait dans le sens de
(sans parler du possible dépassement de tampon, ce n'est qu'un simple exemple)
char string[256];
scanf( "%s" , string );
Cependant, ce qui suit semble fonctionner aussi,
scanf( "%s" , &string );
Est-ce juste mon compilateur (gcc), pure chance ou autre chose?
scanf
, et que la question et la réponse acceptée se concentrent sur cela, et omettez les restrictions cruciales pour la longueur d'entrée maximale qui devraient être utilisées dans le code réel (mais sont d'ailleurs le point de cette question).Réponses:
Un tableau "se désintègre" en un pointeur vers son premier élément, donc
scanf("%s", string)
équivaut àscanf("%s", &string[0])
. En revanche,scanf("%s", &string)
passe un pointeur verschar[256]
, mais il pointe vers le même endroit.Ensuite
scanf
, lors du traitement de la queue de sa liste d'arguments, essaiera d'extraire un fichierchar *
. C'est la bonne chose lorsque vous avez passéstring
ou&string[0]
, mais lorsque vous êtes passé,&string
vous dépendez de quelque chose que la norme de langage ne garantit pas, à savoir que les pointeurs&string
et&string[0]
- les pointeurs vers des objets de types et de tailles différents commencer au même endroit - sont représentés de la même manière.Je ne crois pas avoir jamais rencontré un système sur lequel cela ne fonctionne pas, et dans la pratique, vous êtes probablement en sécurité. Néanmoins, c'est faux et cela pourrait échouer sur certaines plates-formes. (Exemple hypothétique: une implémentation de «débogage» qui inclut des informations de type avec chaque pointeur. Je pense que l'implémentation C sur les «machines Lisp» de Symbolics a fait quelque chose comme ça.)
la source
&string
fonctionne de la même manière questring
(au lieu d'entraîner une corruption aléatoire de la mémoire, comme l'affirment à tort d'autres réponses):printf("%x\n%x\n", string, &string);
string
est un pointeur et&string
est l'adresse de ce pointeur, donc les deux ne sont PAS interchangeables. Comme l'explique Gareth, même pour le cas de la décroissance du tableau,string
et ne&string
sont techniquement pas les mêmes types (même s'ils se trouvent être interchangeables pour la plupart des architectures), et gcc donnera un avertissement pour votre deuxième exemple si vous allumez-Wall
.Je pense que ce ci-dessous est exact et cela peut aider. N'hésitez pas à le corriger si vous trouvez des erreurs. Je suis nouveau chez C.
y compris le caractère nul de terminaison
'\0'
&str
,&str[0]
etstr
, tous les trois représentent le même emplacement en mémoire qui est l'adresse du premier élément du tableaustr
char * strPtr = & str [0]; // déclaration et initialisation
Sinon, vous pouvez diviser cela en deux:
strPtr
est un pointeur vers unchar
strPtr
points au tableaustr
strPtr
est une variable avec sa propre adresse en mémoirestrPtr
est une variable qui stocke la valeur de l'adresse&str[0]
strPtr
sa propre adresse en mémoire est différente de l'adresse mémoire qu'elle stocke (adresse du tableau en mémoire aka & str [0])&strPtr
représente l'adresse de strPtr elle-mêmeJe pense que vous pouvez déclarer un pointeur vers un pointeur comme:
déclare et initialise avec l'adresse du pointeur strPtr
Vous pouvez également diviser en deux:
*vPtr
pointe sur le pointeur strPtr*vPtr
est une variable avec sa propre adresse en mémoire*vPtr
est une variable qui stocke la valeur de l'adresse & strPtrstr++
, l'str
adresse est unconst
, mais vous pouvez le fairestrPtr++
la source