63 votes

Où se trouvent les paramètres de la fonction principale du C/C++ ?

En C/C++, la fonction principale reçoit des paramètres qui sont de type char* .

int main(int argc, char* argv[]){
  return 0;
}

argv est un tableau de char* ils désignent des chaînes de caractères. Où se trouvent ces chaînes ? Sont-elles sur le tas, la pile ou autre chose ?

31voto

John Bode Points 33046

Voici ce que la norme C ( n1256 ) dit :

5.1.2.2.1 Démarrage du programme
...
2 S'ils sont déclarés, les paramètres de la fonction principal doit obéir aux contraintes suivantes contraintes :

  • La valeur de argc doit être non négatif.

  • argv[argc] doit être un pointeur nul.

  • Si la valeur de argc est supérieure à zéro, les membres du tableau argv[0] par le biais de argv[argc-1] inclusif doit contenir des pointeurs vers des chaînes de caractères, auxquelles sont attribuées des valeurs définies par l'environnement hôte avant le démarrage du programme. Le site intention est de fournir au programme des informations déterminées avant le démarrage du programme à partir d'autres éléments de l'environnement hôte. Si l'environnement hôte n'est pas capable de fournir des chaînes de caractères avec des lettres à la fois en majuscules et en minuscules, l'implémentation doit s'assurer que les chaînes sont reçues en minuscules.

  • Si la valeur de argc est supérieure à zéro, la chaîne pointée par argv[0] représente le nom du programme ; argv[0][0] doit être le caractère nul si le nom du programme n'est pas disponible dans l'environnement hôte. Si la valeur de argc est supérieur à un, les chaînes de caractères pointées par argv[1] par le biais de argv[argc-1] représentent le paramètres du programme .

  • Les paramètres argc y argv et les chaînes de caractères pointées par les argv Le tableau doit modifiables par le programme et conservent leur dernière valeur stockée entre le démarrage et la fin du programme. le démarrage et la fin du programme.

Le dernier point est le plus intéressant en ce qui concerne l'endroit où les valeurs des chaînes sont stockées. Il ne spécifie pas de tas ou de pile, mais il exige que les chaînes soient accessibles en écriture et aient une étendue statique, ce qui place algunos des limites sur l'emplacement du contenu de la chaîne. Comme d'autres l'ont dit, les détails exacts dépendront de l'implémentation.

30voto

Stu Points 7999

Il s'agit d'une magie du compilateur, qui dépend de l'implémentation.

19voto

JeremyP Points 46808

Il s'agit en fait d'une combinaison de dépendance vis-à-vis du compilateur et du système d'exploitation. main() est une fonction comme n'importe quelle autre fonction C, donc l'emplacement des deux paramètres argc y argv suivront le standard du compilateur sur la plate-forme. Par exemple, pour la plupart des compilateurs C ciblant x86, ils seront sur la pile juste au-dessus de l'adresse de retour et du pointeur de base sauvegardé (la pile croît vers le bas, rappelez-vous). Sur x86_64, les paramètres sont passés dans des registres, donc argc sera dans %edi y argv sera dans %rsi . Le code de la fonction principale généré par le compilateur les copie ensuite sur la pile, et c'est là que pointent les références ultérieures. Ceci afin que les registres puissent être utilisés pour les appels de fonctions de main .

Le bloc de char* s que argv pointe et les séquences de caractères réelles peuvent être n'importe où. Elles commenceront à un endroit défini par le système d'exploitation et pourront être copiées par le code de préambule que l'éditeur de liens génère sur la pile ou ailleurs. Vous devrez regarder le code de exec() et le préambule assembleur généré par le linker pour le découvrir.

8voto

Baltasarq Points 5164

La réponse à cette question dépend du compilateur. Cela signifie qu'elle n'est pas traitée dans le standard C, donc n'importe qui peut l'implémenter comme il ou elle le souhaite. C'est normal, car les systèmes d'exploitation n'ont pas non plus de méthode standard et communément acceptée pour démarrer et terminer les processus.

Imaginons un simple scénario du type "pourquoi pas".

Le processus reçoit par un certain mécanisme les arguments écrits dans la ligne de commande. argc est alors juste un int qui est poussé sur la pile par la fonction bootstrap que le compilateur a mis comme point d'entrée pour le processus du programme (partie du runtime). Les valeurs réelles sont obtenues du système d'exploitation, et peuvent être, par exemple, écrites dans un bloc de mémoire du Heap. Ensuite, le vecteur argv est construit et l'adresse de sa première position est également poussée dans la pile.

Ensuite, la fonction main(), qui doit être fournie par le programmeur, est appelée et sa valeur de retour est enregistrée pour une utilisation ultérieure (presque immédiate). Les structures du Heap sont libérées, et le code de sortie obtenu pour main est exporté vers le système d'exploitation. Le processus se termine.

3voto

horsh Points 1879

Ces paramètres ne sont pas différents des paramètres de toute autre fonction. Si la séquence d'appel de l'architecture exige que les paramètres passent par la pile, ils sont sur la pile. Si, comme sur x86-64, certains paramètres vont dans les registres, ils vont également dans les registres.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X