Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

scanf et fgets

38 réponses
Avatar
Julien
bonjour

Je fais actuellement les exercices de http://www.france-ioi.org/
d'ailleurs si vous avez d'autres sites avec des exercices, je suis
int=E9ress=E9.

Je me posais la question, un scanf est-il dangereux pour r=E9cup=E9rer un
entier saisi par l'utilisateur.

est ce que :=20

char chaine[1000];
signed int valeur;
=20
(void) fgets(chaine, (int) sizeof(chaine), stdin);
valeur =3D atoi(chaine);

est plus s=FBr que=20

signed int valeur;
scanf("%i",&valeur);

d'autant que l=E0 je ne peux pas mettre conna=EEtre la taille maximale de
l'entier.

J'ai essay=E9 un char chaine[INT_MAX] mais =E7a n'a pas compil=E9.

Merci de vos avis.

--=20
Julien <Juke@free.fr>

10 réponses

1 2 3 4
Avatar
Thierry PINELLI
Mickaël Wolff wrote:


je pense que le type 'int' est, sauf indication contraire, "signed"


Ça dépend de la machine, et du choix d'implémentation du compilateur.


Non, cela dépend de la norme, peu importe la taille des indiens
Si la norme dit que, sauf indication contraire, un "int" est signé
alors "signed int" est un pléonasme.

<http://www.network-theory.co.uk/docs/gccintro/gccintro_71.html>


Le C existait avant GNU/Linux. La référence à Linux et MS_Win me parait
complètement déplacée. La présence de RMS également


Bref, comme toujours, tu as fait le choix de l'a priori, comme nous le
faisons tous ;) Les programmeurs sont incorrigibles.


Je n'ai jamais vu de "signed int" dans les sources que j'ai regardés.
Ce n'est pas un a priori, c'est une constatation


Avatar
Mickaël Wolff

Non, cela dépend de la norme, peu importe la taille des indiens
Si la norme dit que, sauf indication contraire, un "int" est signé
alors "signed int" est un pléonasme.


Et c'est dit où qu'un int doit être signé ?

<http://www.network-theory.co.uk/docs/gccintro/gccintro_71.html>


Le C existait avant GNU/Linux. La référence à Linux et MS_Win me parait
complètement déplacée.


Pourquoi serait-ce déplacé ? Ce sont des exemples de cas pratique, pas
des affirmations absolues :

« Most systems, including x86 GNU/Linux and Microsoft Windows, use
signed char, but those based on PowerPC and ARM processors typically use
unsigned char. »

« La plupart des systèmes, dont GNU/Linux x86 et Microsoft Windows,
utilisent signed char, mais ces systèmes d'exploitation utilisent des
unsigned char lorsqu'ils sont basés sur des processeurs PowerPC ou ARM »

Ce qui veut donc dire qu'on ne peut pas supposer que la déclaration
d'un int sera assurément un signed int.

La présence de RMS également


Il n'est pas une référence ? Je crois qu'il connais assez intimement
le C pour pouvoir donner des explications sur ce que lui et ses
collaboateurs ont implémenté dans GCC.

Je n'ai jamais vu de "signed int" dans les sources que j'ai regardés.
Ce n'est pas un a priori, c'est une constatation


C'est un a priori, et je n'en démordrai pas. Mais cela ne pose pas de
problème, si l'entier attendu par le système du programme fils est bien
l'entier donné. Non ?

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org


Avatar
Mickaël Wolff
(Marc Espie) writes:

Comme ce que tu racontes n'est pas clair du tout, un petit resume
rapide des regles de base de portabilite des types entiers:


Tu oublies que les bitfields (pour Mickael, i dans struct s { int i:5; };
et *pas* tous les objets entiers) sont aussi un cas particulier où il faut
préciser le signe si ça a de l'importance.


J'ai effectivement mal compris ce qu'ils entendaient par bitfields.

Merci pour ces éclaircissements en tou cas !
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org


Avatar
Mickaël Wolff

Ah bon ? Par convention sizeof(char) vaut 1, le char etant la reference
des tailles memoires.


Convention ne veut pas dire norme, hein ;)

Mais il n'y a pas de taille imposee pour char ni pour int (seulement des
plages minimales de valeur).


On est d'accord là-dessus.

Ben justement non, je ne vois rien dans l'article qui generalise ce fait
a tous les types entiers.


Au temps pour moi, j'ai lu trop vite en sautant le mot « struct » dans
la locution « bitfields in struct ».

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Avatar
Jean-Marc Bourguet
Mickaël Wolff writes:


Ah bon ? Par convention sizeof(char) vaut 1, le char etant la reference
des tailles memoires.


Convention ne veut pas dire norme, hein ;)


C'est dans la norme.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
espie
In article <46f57267$0$32149$,
Mickaël Wolff wrote:

Non, cela dépend de la norme, peu importe la taille des indiens
Si la norme dit que, sauf indication contraire, un "int" est signé
alors "signed int" est un pléonasme.


Et c'est dit où qu'un int doit être signé ?


Paragraphe 6.2.5.4
`There are five standard signed integer types, designated as
signed char, short int, int, long int, and long long int. (These
and aother types may be designated in several additional ways, as described
in 6.7.2).

et 6.7.2.2 donne explicitement les equivalences entre types entiers sous
forme de `type specifier'. Re-extrait:
- void
- char
- signed char
- unsigned char
- short, signed short, short int, or signed short int
- unsigned short, or unsigned short int
- int, signed, or signed int
- unsigned, or unsigned int
- long, signed long, long int, or signed long int
- unsigned long, or unsigned long int
- long long, signed long long, long long int, or signed long long int
- unsigned long long, or unsigned long long int
[...]

Trouve-toi une norme, ou au moins un Kernighan&Richie, et arrete de
poster des conneries.


Avatar
Thierry PINELLI
Mickaël Wolff wrote:

Et c'est dit où qu'un int doit être signé ?


faut arreter la bière. personne n'a écrit cela


Pourquoi serait-ce déplacé ? Ce sont des exemples de cas pratique, pas
des affirmations absolues :


C'est de la pub pour un bouquin.

« La plupart des systèmes, dont GNU/Linux x86 et Microsoft Windows,
utilisent signed char, mais ces systèmes d'exploitation utilisent des
unsigned char lorsqu'ils sont basés sur des processeurs PowerPC ou ARM »


la question d'origine portait sur "signed int" qui est un pléonasme

Ce qui veut donc dire qu'on ne peut pas supposer que la déclaration
d'un int sera assurément un signed int.


c'est un int signé tant que tu ne le déclare pas unsigned

capito ?


Je n'ai jamais vu de "signed int" dans les sources que j'ai regardés.
Ce n'est pas un a priori, c'est une constatation


C'est un a priori, et je n'en démordrai pas. Mais cela ne pose pas de
problème, si l'entier attendu par le système du programme fils est bien
l'entier donné. Non ?


non, c'est une constatation. Point barre


Avatar
Antoine Leca
En news:fd2cc1$9hs$, Thierry PINELLI va escriure:
Julien wrote:
signed int valeur;


que dit la norme au sujet de ce type ?


Que c'est un « /type entier signé standardisé/ » (C99 6.2.5a4).
L'alinéa suivant ajoute qu'un objet de ce type « a la taille naturellement
sugérée par l'architecture cible », moyennant la contrainte de contenir au
moins l'intervalle [-32767, +32767].

Pourquoi cette question ?


Antoine


Avatar
Antoine Leca
En news:46f4e701$0$8908$, Mickaël Wolff va escriure:
je pense que le type 'int' est, sauf indication contraire, "signed"


Ça dépend de la machine, et du choix d'implémentation du
compilateur.


NON.
Un compilateur C qui implémenterait int comme non-signé serait très
marginal, évidemment non conforme à la norme, et poserait d'énormes
problèmes potentiels de portabilité.

Un seul exemple : getc() indique un cas d'erreur en retournant EOF, une
constante entière négative ; beaucoup de code utilise l'idiome:
if( getc(...) < 0 ) { /* fini: */
Et avec des int non signé, on n'a jamais fini...


Antoine


Avatar
Antoine Leca
En news:, Julien va escriure:
Je me posais la question, un scanf est-il dangereux pour récupérer un
entier saisi par l'utilisateur.


Définit « dangereux ».

gets() est dangereux, car le seul moyen d'empêcher des possibles
débordements de pile, c'est de contrôler l'entrée ! (la démonstration à
l'échelle de l'Internet date de 1988.)

Pour le reste, scanf(), strtok(), strncat() etc. sont dangereux car on peut
facilement se tromper en les utilisant mal. Cependant le « danger » est
d'une toute autre nature que le précédent.


est ce que :

(void) fgets(chaine, ...
valeur = atoi(chaine);

est plus sûr que

scanf("%i",&valeur);


Entre Charybde et Scylla... En fait, la première version est pire si
chaîne[] est une locale, avec une entrée vide cela donne généralement
SIGSEGV.


J'ai essayé un char chaine[INT_MAX] mais ça n'a pas compilé.


:-)

1 2 3 4