Comportement de scanf ()

Dupliquer possible:
confusion dans scanf () avec l’opérateur &

Pourquoi nous avons besoin d’un & in scanf pour saisir un entier et pourquoi pas pour des caractères. Est-ce que le & in scanf fait référence au lieu de mémoire lors de la saisie?

Par exemple:-

main() { int a; char c; scanf("%d",&a); scanf("%c"c); } 

Pour chaque spécificateur de conversion, scanf() s’attend à ce que l’argument correspondant soit un pointeur sur le type approprié: %d attend un argument de type int * , %f attend un argument de type double * , %c et %s attendent tous deux un argument de type char * , etc.

La différence entre %c et %s réside dans le fait que le premier indique à scanf() de lire un seul caractère et de le stocker à l’emplacement spécifié par l’argument correspondant, tandis que le second indique à scanf() de lire plusieurs caractères jusqu’à voir apparaître un caractère 0- valeur et enregistrez tous ces caractères dans la mémoire tampon en commençant à l’emplacement spécifié par l’argument.

Vous devez utiliser l’opérateur & sur vos arguments s’ils ne sont pas déjà de type pointeur. Par exemple:

 int x; int *px = some_valid_memory_location_such_as_&x; char c; char *pc = some_valid_memory_location_such_as_&c; ... scanf("%d", &x); // x is not a pointer type, so we must use the & operator scanf("%d", px); // px is a pointer type, so we don't need the & operator scanf("%c", &c); // etc. scanf("%c", pc); // etc. 

La lecture de chaînes de caractères (à l’aide du spécificateur de conversion %s ) est source de confusion:

 char buf[SIZE]; scanf("%s", buf); // expression 'buf' *implicitly* converted to pointer type 

Pourquoi n’avons-nous pas besoin de l’opérateur & dans ce cas? Cela a à voir avec la façon dont C traite les expressions de tableau. Lorsque le compilateur voit une expression de type tableau (tel que buf dans l’appel scanf() ), il convertit implicitement l’expression du type N-element array of T en pointer to T , et définit sa valeur sur l’adresse du premier élément dans le tableau. Cette valeur n’est pas une valeur – elle ne peut pas être affectée (vous ne pouvez donc pas écrire quelque chose comme buf = foo ). Les seules exceptions à cette règle concernent le cas où l’expression de tableau est un opérande des opérateurs sizeof ou & , ou si l’expression de tableau est un littéral utilisé pour initialiser un autre tableau:

 char *p = "This is a test"; // ssortingng literal implicitly converted to char *, // ssortingng *address* written to p char a[] = "This is a test"; // ssortingng literal not implicitly converted, // ssortingng *contents* copied to a 

En bref, l’expression buf est convertie implicitement de type char [SIZE] à char * . Il n’est donc pas nécessaire d’utiliser l’opérateur & , et en fait, le type de l’expression &buf serait pointer to SIZE-element array of char , ou (*)[SIZE] , ce qui n’est pas ce que scanf() attend du spécificateur de conversion %s .

Le symbole esperluette est requirejs dans les deux cas. scanf nécessite des pointeurs (vous pensiez probablement à char * ou char [] – ce sont des pointeurs eux-mêmes).

Scanf lit les entrées sur une adresse mémoire. a est la valeur détenue par a. &a est l’emplacement d’ a en mémoire.

Dans votre code ci-dessus, le c devrait être &c .

Parce que scanf() besoin de pointeurs, et &a est le pointeur sur un entier.

Dans votre exemple, vous avez besoin d’une virgule et d’une esperluette devant le c .

 int main(void) { int a; char c; char s[21]; scanf("%d",&a); scanf("%c", &c); // Fixed! scanf("%20s", s); printf("a = %d, c = %c, s = <<%s>>\n", a, c, s); } 

Si vous lisiez une chaîne, vous passeriez la chaîne – un pointeur sur char – vers scanf() .

Vous devez fournir à scanf un pointeur, c’est pourquoi vous avez & in scanf (“% d”, & a) ; . scanf (“% c” c) ; ne fonctionnera pas du tout.

Votre exemple est faux. Si tu as un

 char c; 

alors vous devez append un & au nom lorsque vous appelez scanf :

 scanf("%c", &c); 

Cependant , si votre variable est déjà un pointeur, par exemple parce que c’est un caractère char[] (qui est une syntaxe élégante pour les pointeurs), vous devez omettre le & .

J’aime penser à l’esperluette (&) comme “adresse de”. Donc, vous lisiez &a comme “adresse d’un”.

De plus, j’ai essayé de le comstackr mais il m’a averti sur gcc:

 Warning: format "%c" expects type 'char *', but argument 2 has type 'int' 

Ce qui est vrai, car un caractère est fondamentalement un int.