Pourquoi ne pas utiliser (void) dans main?

les Gens utilisent void main() /*empty parens ()*/

on m'a appris à écrire void main(void)

Quelle est la différence?

30
c
demandé sur tom 2010-07-01 13:13:04

5 réponses

Je ne suis pas sûr de ce que sont les normes de nos jours, mais dans l'Anse traditionnelle, en utilisant des parenthèses vides indique que la fonction peut prendre n'importe quel nombre d'arguments. Déclarer un paramètre void d'autre part indique que la fonction ne prend que des arguments zéro . Dans ce cas (et bien d'autres), il vraiment n'importe pas trop.

si vous voulez être strict cependant, il est probablement préférable de définir le void paramètre. Bien sûr, la fonction main peut aussi être définie comme int main(int argc, const char* argv[]) - ce qui est parfaitement valide, mais souvent inutile si vous ne vous souciez pas des arguments.

35
répondu Noldorin 2017-12-02 05:20:39

de la norme C99:

5.1.2.2.1 démarrage du programme

La fonction appelée au démarrage du programme est nommé principal. La mise en œuvre déclare non prototype pour cette fonction. Il doit être défini avec un type de retour int et sans paramètres:

int main(void) { /* ... */ }

ou avec deux paramètres (appelés ici argc et argv, bien que n'importe quels noms peuvent être utilisées car elles sont locales à la fonction dans dont ils sont déclarés):

int main(int argc, char *argv[]) { /* ... */ }

ou l'équivalent; ou d'une autre manière définie par la mise en œuvre.

lorsque main est défini sans paramètres, argc et argv seront-ils toujours présents sur la cheminée?

18
répondu Tim Schaeffer 2017-05-23 12:02:43

ces prototypes de main () sont tous deux non standard.

des précisions sur cette question se trouvent sur le comp.lang.C faq: http://c-faq.com/decl/main.html

EDIT : changé "wrong" en "non-standard" car la norme permet la mise en œuvre de prototypes définis.

5
répondu Gery 2010-07-01 19:03:45

il n'y a pas de différence, mais main devrait normalement retourner int. Certains compilateurs vous donneront un avertissement (au moins le compilateur GNU-gcc):

$ cat x.c
void main(void){}

$ gcc x.c
x.c: In function `main':
x.c:1: warning: return type of 'main' is not `int'

comme mentionné le prototype de main est (selon la norme):

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

2
répondu INS 2010-07-01 11:13:55

main est une fonction, comme d'autres fonction. Presque. Quoi qu'il en soit, étant une fonction, elle est appelée par un autre code (un code de démarrage). Généralement (lire: presque toujours) int main() est le bon, mais en effet ce qui est le réel correcte dépend de la plate-forme de travail. Puisque, comme dit, la fonction principale pourrait être appelée par un code de démarrage qui ne passe en aucun argument, et qui n'attend aucune valeur de retour dans un registre spécifique (de sorte que void main(void) est correct).

le int main() est correct puisque normalement le code de démarrage attendent une valeur de retour, et passent dans deux arguments. En disant int main(void) vous dites main ne prend aucun argument du tout, qui est faux dans la plupart des cas. Avec () vous dites qu'il y a des arguments (Un, Deux, Trois, vous vous en fichez), mais vous n'êtes pas intéressé par eux, donc vous n'êtes pas intéressé à dire ce qu'ils sont et quel type ils sont.

comme je peux le voir dans les codes, le plus utilisé prototype pour des environnements " normaux "(pas de périphérique intégré ou d'autres environnements" étranges "où main peut être appelé différemment) est int main() quand vous ignorez les arguments passés int argc, char **argv . (GCC se plaindre car nous utilisons une version pour gcc adapté à l'environnement; tester avec cross GCC version pour l'un des environnement où le code de démarrage ne passe pas d'arguments et ne s'attendre à aucune valeur de retour)

modifier

juste pour être gentil aux sceptiques; sur un environnement où la fonction principale est appelée, avec deux arguments ,le suivant

int func()
{
  return 0;
}

int func2(void)
{
  return 1;
}

int main(void)
{
  int a;
  a = func(a, a); /* A */
  a = func2(a);   /* B */
  return 0;
}

dit pas d'erreur pour A, tandis que pour B dit too many arguments to function ‘func2’ , compilé avec gcc -std=c99 -pedantic . Changer int main(void) en int main() ne fait aucune différence, et aucun avertissement.

sur d'autres environnements (Je ne peux pas faire de tests pratiques maintenant), void main(void) est ok, alors que dans ce cas il soulève un avertissement. Le avertissement n'est pas seulement à cause de la norme, mais seulement parce que dans l'environnement en usage le prototype pour main ne correspond pas. Standard semble permettre toute autre "configuration" pour main.

dans le cas OP, considérant l'environnement "normal" (O. S. comme GNU / Linux par exemple), où deux args sont passés à la main, et une valeur de retour est attendue, le int main() est préférable (les arguments sont poussés sur la pile par le code de démarrage que vous disiez int main(void) ou non, donc int main() pour moi plus de sens)

modifier

encore une note, toujours pour les sceptiques. Comme déjà prouvé, B soulève une erreur, puisque j'ai dit qu'il est int func2(void) mais je l'appelle passer un argument. Supposons ensuite que nous puissions compiler le code de démarrage et le lier, comme tout autre code. Quelque part, il appellera le main, d'une manière comme

retval = main(argc, argv);

si nous avons utilisé int main(void) , le compilateur s'arrêtera, donnant une erreur, puisque le code de démarrage (dans cet environnement) essaye d'appeler main avec deux arguments. Si nous utilisons int main() , rien ne se produit et le code est compilé correctement.

, int main() est supérieure à int main(void) (dans l'environnement où nous nous attendons à deux arguments principaux possible)

modifier

plus probable l'appel est comme

retval = main(_argc, _argv, environ);

sur de nombreux systèmes, mais cela ne change pas le précédent discours.

final edition

est-ce que quelqu'un a trouvé que lors de la construction d'un outil en ligne de commande (i.e. sur les systèmes où int argc, char ** a un sens) avec int main(void) , le compilateur/linker choisi lie un code de démarrage où le main est appelé sans arguments (quelles que soient les conventions d'appel), et à la place lors de la construction avec int main(int argc, char **argv) le code de démarrage est différent et appelle en fait main avec ces deux arguments (même si le main lui-même ne les utilise pas)?

1
répondu ShinTakezou 2016-11-05 14:11:45