|
Titre: Pourquoi le programme fonctionne ? Posté par: Creaprog le 13 Décembre 2016 à 12:48:28 Bonjour,
Je rencontre un problème, une incompréhension en C. Code: int main(void) { char *user; user = "toto"; puts(user); } Le code fonctionne, mais je ne comprend pas. char *user permet de stocker l'adresse d'un char. Ensuite on essaye de mettre 4bytes dans l'adresse d'un char... Voici pour moi un code qui marche (oui c'est chelou une correction d'un code qui marche...) Code: int main(void) { char *user = "toto"; puts(user); } Cela fait 8 mois que je n'ai pas fait de C donc rester cool avec moi =) Je suis sur mon Mac et je n'ai pas de Linux actuellement sous la main, impossible de faire un valgrind :? Titre: Re : Pourquoi le programme fonctionne ? Posté par: Creaprog le 13 Décembre 2016 à 17:51:57 Merci pixis. Si je ne dit pas de connerie.
Dans le premier cas, on créer un pointeur de type char, ensuite il créer la chaine de caractère. Dans le deuxième cas, on sa créer direct la chaine de caractère. Titre: Re : Pourquoi le programme fonctionne ? Posté par: dionosis le 13 Décembre 2016 à 18:40:35 Salut,
En fait tes deux extraits de code sont strictement équivalents. :) Le type de la variable 'user' c'est (char*) et non pas (char). C'est probablement plus clair comme ça : Code: void foo() { typedef char* pChar pChar user; user = "toto"; puts(user); } Donc tu vois bien que le faire sur une ligne ou sur deux revient au même. Quant au fait que tu puisses utiliser ce genre d'égalité, c'est simplement une facilité offerte par le compilateur. Ce qu'il se passe derrière c'est ça : Citation void foo() { static char _totoString[4+1] = "toto"; // 8 en réalité pour alignement, dans le tas (section datas initialisées du binaire loadé), donc scope local mais lifetime global, et initialisé au loadtime et non pas au runtime char *user; user = &_totoString[0]; puts(user); } Ca sera sûrement plus parlant comme ça. ;) ++ Ps: Je ne vois pas la réponse de pixis dont tu parles ?! Titre: Re : Pourquoi le programme fonctionne ? Posté par: the lsd le 13 Décembre 2016 à 19:34:06 La réponse de pixis était sur irc, j'ai dit que ça serait cool de l'écrire sur le forum une fois qu'ils auraient fini d'en parler, mais j'ai pas préciser comment l'écrire ^^'
Par contre, je suis d'accord avec dionosis, mais de ce que j'en ai compris sur irc, les deux codes n'étaient pas équivalent et l'un d'eux aurait pas du fonctionner (pas suivi tout l'affaire non plus) Enjoy The lsd Titre: Re : Pourquoi le programme fonctionne ? Posté par: dionosis le 13 Décembre 2016 à 21:07:02 Re,
Dac, ma réponse est correcte pour le code cité dans le post original, mais je vais tacher d'énumérer les autres différents cas de figure pour clarifier. Le code suivant (cas 1) : Code: char *user; void foo() { user = "toto"; puts(user); } équivaut à : Code: static char _totoString[4+1] = "toto"; // 8 en réalité pour alignement, dans un TAS (section datas INITIALISEES du binaire loadé), scope GLOBAL et lifetime GLOBAL, initialisé au LOADTIME static char *user; // pointeur donc 4 ou 8 selon si 32 ou 64 bits, dans un TAS (section datas NON INITIALISEES du binaire loadé), scope GLOBAL et lifetime GLOBAL, initialisé au RUNTIME void foo() { user = &_totoString[0]; // RUNTIME puts(user); } Le code suivant (cas 2) : Code: char *user = "toto"; void foo() { puts(user); } équivaut à : Code: static char user[4+1] = "toto"; // 8 en réalité pour alignement, dans un TAS (section datas INITIALISEES du binaire loadé), scope GLOBAL et lifetime GLOBAL, initialisé au LOADTIME void foo() { puts(user); } Le code suivant (cas 3) : Code: void foo() { char user[4+1] = "toto"; puts(user); } équivaut à (Edit2: en 32 bits, si la version 64 bits vous intéresse faites le moi savoir) : Code: void foo() { char user[4+1]; // 8 en réalité pour alignement, dans la PILE, scope LOCAL et lifetime LOCAL, initialisé au RUNTIME register unsigned int *pUser; // pointeur donc 4 ou 8 selon si 32 ou 64 bits, dans un REGISTRE, scope LOCAL et lifetime LOCAL, initialisé au RUNTIME pUser = (unsigned int *)&user[0]; // RUNTIME *pUser = 0x6F746F74; // dans le cas d'une architecture low-endian pUser++; // arithmétique pointeurs donc +4 ici en 32 bits *pUser = 0; // null terminated puts(user); } MAIS pourra si la chaîne est trop longue et selon l'optimisation être traduit vers justement le cas 0 de ma réponse initiale ! C'est ce cas qui est ambigü. Le code suivant (cas 4) : Code: char user[4+1]; void foo() { user = "toto"; puts(user); } et le code suivant (cas 5) : Code: void foo() { char user[4+1]; user = "toto"; puts(user); } sont incorrects. Il faudra employer une méthode/fonction de copie, ou bien le faire manuellement. Edit1: On m'a demandé de vérifier sous gcc, et donc en fait user[] : - sous visual se comporte comme le cas 0 de ma réponse initiale (*user, conforme) - sous gcc/mingw se comporte comme le cas 3 de cette réponse ci (user[n_auto], non conforme, et donc ambigu aussi) Arf, ça m'apprendra à vouloir répondre en 5 minutes quand c'est merdeux comme ça. :lol: ++ Titre: Re : Pourquoi le programme fonctionne ? Posté par: pixis le 13 Décembre 2016 à 23:49:43 Avec la première réponse, dionosis avait résumé grosso modo ce que j'avais raconté sur IRC :)
Titre: Re : Pourquoi le programme fonctionne ? Posté par: the lsd le 14 Décembre 2016 à 11:41:10 En tout cas, GG pour ta réponse de ouf dionosis ! :)
Enjoy The lsd Titre: Re : Pourquoi le programme fonctionne ? Posté par: Creaprog le 14 Décembre 2016 à 16:56:25 architecture low-endian == Endianness ?
Code: *pUser = 0x6F746F74; // dans le cas d'une architecture low-endian Comment il a deviner l'adresse au pif ?Titre: Re : Pourquoi le programme fonctionne ? Posté par: dionosis le 14 Décembre 2016 à 20:26:01 Salut,
Citation de: Creaprog Comment il a deviner l'adresse au pif ? - '*pUser' est la valeur pointée, 'pUser' est le pointeur. Go cours C sur les pointeurs (en fait je crois que c'est ça ton problème à la base).- "toto" en hexa c'est "\x74\x6F\x74\x6F" (+ "\x00" final). Inversé en low-endian. Go cours C sur les chaînes null terminated + cours d'architecture. ++ Titre: Re : Pourquoi le programme fonctionne ? Posté par: Creaprog le 14 Décembre 2016 à 21:49:01 Salut,
Merci de ton message j'ai relu encore et encore. Merci de m'avoir mit en pls. J'ai fais avant du C mais en bâclant, aujourd'hui je souhaite le reprendre avec des bases solides. Titre: Re : Pourquoi le programme fonctionne ? Posté par: dionosis le 15 Décembre 2016 à 02:03:21 Salut,
De rien ;) Bonne continuation. ++ |