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

prototype de la fonction main : pourquoi argc est il signé ?

22 réponses
Avatar
hibakusha
Bonjour à tous.

Pour le protoype suivant de main :

int main(int argc, char* argv[])

la norme indique pour argc :

"The value of argc shall be nonnegative."

L'utilisation de "shall" est perturbante, et je me demande ce qu'il
faut comprendre ici : est ce que cela veut bien dire que argc DOIT être
positif ? Et dans ce cas, pourquoi argc est il de type "int", c'est à
dire potentiellement négatif ?

Est ce moi qui comprends mal cette définition, ou bien y a t il la une
bizarerie, héritage quelconque d'un comportement etrange de certaines
version d'unix ou je ne sais quelle autre explication ?

Clairement, je me demande si il existe certaines situations où argc peut
être négatif ?

Et je me pose cette question avant de partir en vacances, c'est un signe...

Merci d'apporter vos lumieres sur le sujet...

(Je suis sûr que la question à déja été posée, mais je n'arrive pas a
mettre la main sur une réponse)

10 réponses

1 2 3
Avatar
Jean-Marc Bourguet
hibakusha writes:

Bonjour à tous.

Pour le protoype suivant de main :

int main(int argc, char* argv[])

la norme indique pour argc :

"The value of argc shall be nonnegative."

L'utilisation de "shall" est perturbante, et je me demande ce qu'il
faut comprendre ici : est ce que cela veut bien dire que argc DOIT être
positif ?


In this International Standard, shall is to be interpreted as a requirement
on an implementation or on a program; conversely, shall not is to be
interpreted as a prohibition.

Et dans ce cas, pourquoi argc est il de type "int", c'est à dire
potentiellement négatif ?


L'histoire, vraisemblablement.

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
Pascal Bourguignon
hibakusha writes:

Bonjour à tous.

Pour le protoype suivant de main :

int main(int argc, char* argv[])

la norme indique pour argc :

"The value of argc shall be nonnegative."

L'utilisation de "shall" est perturbante, et je me demande ce qu'il
faut comprendre ici : est ce que cela veut bien dire que argc DOIT être
positif ? Et dans ce cas, pourquoi argc est il de type "int", c'est à
dire potentiellement négatif ?

Est ce moi qui comprends mal cette définition, ou bien y a t il la une
bizarerie, héritage quelconque d'un comportement etrange de certaines
version d'unix ou je ne sais quelle autre explication ?

Clairement, je me demande si il existe certaines situations où argc
peut être négatif ?

Et je me pose cette question avant de partir en vacances, c'est un signe...

Merci d'apporter vos lumieres sur le sujet...

(Je suis sûr que la question à déja été posée, mais je n'arrive pas a
mettre la main sur une réponse)


Tout le monde est d'accord, ce serait mieux si c'était déclaré
unsigned int argc.

Mais le mélange de types entier N-bit non signés et de types entier
N-bit signés en complément à deux est toujours problématique, car les
intervales ne sont pas imbriqués, mais ont une intersection bizarre.

En C, on le voit par les différent warnings qu'un compilateur donne,
et sur les erreurs invisible comises quand on mélange les deux.

En Modula-2, on a un type INTEGER et un type CARDINAL, et c'est à peu
près géré correctement mais ce n'est pas parfait.

En Oberon, le problème est résolu: il n'y a qu'un type signé INTEGER
(et donc, on ne va que jusqu'à 2^(N-1)-1).

En C, tu peux t'amuser d'essayer de mettre du unsigned int partout où
c'est logique. Tu te rendras vite compte que c'est beaucoup plus
simple de mettre partout du int. (C'est comme pour les const, d'ailleurs).


Finalement, le seule language à ma connaissance qui gère ça
correctement, c'est Common Lisp: on peut déclarer des types entiers de
n'importe quelle taille, signé ou non, et les mélanger comme on veut,
et Lisp s'arrange pour obtenir le résultat mathématiquement correct.


--
__Pascal Bourguignon__ http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

Avatar
hibakusha
Pascal Bourguignon wrote:

Tout le monde est d'accord, ce serait mieux si c'était déclaré
unsigned int argc.


ouf, c'est donc bien une bizarerie... dont j'aimerais quand même
connaitre l'origine.

Je suis persuadé qu'il a forcément existé, dans un lointain passé, un
cas très particulier où le système pouvait passé une valeur négative
pour argc, signifiant par là quelque chose de particulier à prendre en
compte.

Ou bien les penseurs-redacteurs de la norme ont imaginé une utilisation
possible en ce sens, ou dans un autre. Et dans ce cas, qu'ont ils imaginé ?

Ou simplement ils se sont dit qu'un jour cela me turlipinera et en ce
moment ils se marrent comme des baleines.

Avatar
Stephane Legras-Decussy
"hibakusha" a écrit dans le message de news:
46bc902c$0$437$
ouf, c'est donc bien une bizarerie... dont j'aimerais quand même connaitre
l'origine.



je ne trouve pas ça bizarre.

perso j'utilise toujours
des variables signées pour des quantités qui ne
peuvent jamais être negatives.

d'ailleur pourquoi les chaines de caractères
sont des char et pas des unsigned char dans ce cas ?
ça devrait te perturber d'avantage...

pour moi les unsigned ne servent que pour des
masques de bit et les operations logiques...

Avatar
Pierre Maurette
Bonjour à tous.

Pour le protoype suivant de main :

int main(int argc, char* argv[])

la norme indique pour argc :

"The value of argc shall be nonnegative."

L'utilisation de "shall" est perturbante, et je me demande ce qu'il
faut comprendre ici : est ce que cela veut bien dire que argc DOIT être
positif ? Et dans ce cas, pourquoi argc est il de type "int", c'est à
dire potentiellement négatif ?

Est ce moi qui comprends mal cette définition, ou bien y a t il la une
bizarerie, héritage quelconque d'un comportement etrange de certaines version
d'unix ou je ne sais quelle autre explication ?

Clairement, je me demande si il existe certaines situations où argc peut être
négatif ?

Et je me pose cette question avant de partir en vacances, c'est un signe...

Merci d'apporter vos lumieres sur le sujet...

(Je suis sûr que la question à déja été posée, mais je n'arrive pas a mettre
la main sur une réponse)


1 - Il me semble que l'utilisation de int quand elle est "suffisante"
est privilégiée. C'est le type entier par défaut. Voir la norme (§7.4
?) sur <ctype.h>, on y retrouve d'ailleurs le haïssable "shall".

2 - Il me semble que le "shall" s'adresse plutôt au shell ou au loader
qui va lancer main() dans un "hosted environment" avec les arguments
qui vont bien.

3 - Ce truc-là ne semble pas poser de problème, à part son inutilité
flagrante en l'état:

#include <stdio.h>

int main (int argc, char *argv[])
{
if (argc < 0)
{
puts("Recursive call to main()");
}
else
{
while(argc > 0)
{
puts(argv[--argc]);
}
main(-1, NULL);
}
(void)argv;
return 0;
}

--
Pierre Maurette

Avatar
Pierre Maurette

[...]

{
while(argc > 0)
{
puts(argv[--argc]);
}
main(-1, NULL);
}
(void)argv;


Oooops! Dernière ligne inutile, après avoir ajouté l'affichage de la
ligne de commandes.

--
Pierre Maurette

Avatar
candide
On 10 août, 14:45, hibakusha wrote:

(Je suis sûr que la question à déja été posée, mais je n'arri ve pas a
mettre la main sur une réponse)


Elle l'a été a plusieurs reprises sur clc, cf. par exemple

http://groups.google.fr/group/comp.lang.c/msg/3e00366d8431f9bc?hl=fr&amp;

où on retrouve l'argument de l'appel récursif main(-1, NULL).

Avatar
Pascal Bourguignon
Pierre Maurette writes:
2 - Il me semble que le "shall" s'adresse plutôt au shell ou au loader
qui va lancer main() dans un "hosted environment" avec les arguments
qui vont bien.


J'ai essayé de trouver une fonction exec qui prenne un argument argc,
mais non, elles prennent toutes seulement un argv terminé par 0, et
donc logiquement, argc en doit être déduit et ne peut donc pas être
négatif.


3 - Ce truc-là ne semble pas poser de problème, à part son inutilité
flagrante en l'état:

#include <stdio.h>

int main (int argc, char *argv[])
{
if (argc < 0)
{
puts("Recursive call to main()");
}
else
{
while(argc > 0)
{
puts(argv[--argc]);
}
main(-1, NULL);
}
(void)argv;
return 0;
}


Oui. Une fois que main a pris la main, tout est possible.

--
__Pascal Bourguignon__ http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

Avatar
espie
In article <46bc5e13$0$411$,
hibakusha wrote:

Bonjour à tous.

Pour le protoype suivant de main :

int main(int argc, char* argv[])

la norme indique pour argc :

"The value of argc shall be nonnegative."

L'utilisation de "shall" est perturbante, et je me demande ce qu'il
faut comprendre ici : est ce que cela veut bien dire que argc DOIT être
positif ? Et dans ce cas, pourquoi argc est il de type "int", c'est à
dire potentiellement négatif ?

Est ce moi qui comprends mal cette définition, ou bien y a t il la une
bizarerie, héritage quelconque d'un comportement etrange de certaines
version d'unix ou je ne sais quelle autre explication ?


Il y a deux choses: effectivement, c'est un heritage de temps obscurs,
en partie, ou les fonctions n'avaient pas de prototypes, et ou donc
int est le type `naturel' d'un parametre de fonction.

L'autre aspect, c'est que les valeurs non signes se pretent mal a
l'arithmetique: si ton argc entre dans une soustraction, et que le
resultat est negatif, tu es bien content de le savoir...
(je n'ai pas d'exemple non loufoque sous la main).

Avatar
Vincent Lefevre
Dans l'article ,
Pascal Bourguignon écrit:

Tout le monde est d'accord, ce serait mieux si c'était déclaré
unsigned int argc.


Non, je ne suis pas d'accord.

Mais le mélange de types entier N-bit non signés et de types entier
N-bit signés en complément à deux est toujours problématique, car les
intervales ne sont pas imbriqués, mais ont une intersection bizarre.


Voilà, les types non signés posent des problèmes et sont sources de
bugs (une valeur négative se retrouve facilement convertie en valeur
positive). De plus, ils ne permettent pas un contrôle d'overflow via
des traps (cf option -ftrapv de gcc).

Déclarer un type non signé juste parce qu'une valeur négative n'a pas
de sens, c'est idiot.

En C, on le voit par les différent warnings qu'un compilateur donne,
et sur les erreurs invisible comises quand on mélange les deux.


Le compilateur ne donne pas toujours de warning. Le pire, c'est quand
ça marche en 32 bits, mais plus du tout en 64 bits, car les promotions
se font différemment (e.g. une promotion en un type signé devient une
promotion en un type non signé, d'où bug sur les valeurs négatives).

--
Vincent Lefèvre - Web: <http://www.vinc17.org/&gt;
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/&gt;
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)

1 2 3