Pourquoi les adresses de argc et argv sont-elles séparées de 12 octets ?

J'ai exécuté le programme suivant sur mon ordinateur (Intel 64 bits sous Linux).

#include <stdio.h>

void test(int argc, char **argv) {
    printf(&quot ;[test] Argc Pointer : %p\n&quot ;, &argc) ;
    printf(&quot ;[test] Argv Pointer : %p\n&quot ;, &argv) ;
}

int main(int argc, char **argv) {
    printf("Argc Pointer : %p\n&quot ;, &argc) ;
    printf("Argv Pointeur : %p\n&quot ;, &argv) ;
    printf("Taille de &argc : %lu\n&quot ;, sizeof (&argc)) ;
    printf("Taille de &argv : %lu\n&quot ;, sizeof (&argv)) ;
    test(argc, argv) ;
    return 0 ;
}

La sortie du programme était

$ gcc size.c -o size
$ ./size
Pointeur Argc : 0x7fffd7000e4c
Pointeur Argv : 0x7fffd7000e40
Taille de &argc : 8
Taille de &argv : 8
[Test] Pointeur Argc : 0x7fffd7000e2c
[test] Pointeur Argv : 0x7fffd7000e20

La taille du pointeur &argv est de 8 octets. Je m'attendais à ce que l'adresse de argc soit adresse de (argv) + sizeof (argv) = 0x7ffed1a4c9f0 + 0x8 = 0x7ffed1a4c9f8 mais il y a un remplissage de 4 octets entre les deux. Pourquoi est-ce le cas ?

Je pense que cela pourrait être dû à l'alignement de la mémoire, mais je ne suis pas sûr.

Je remarque le même comportement avec les fonctions que j'appelle également.

Commentaires sur la question (6)
Solution

Sur votre système, les premiers arguments de type entier ou pointeur sont passés dans des registres et n'ont pas d'adresse. Lorsque vous prenez leurs adresses avec &argc ou &argv, le compilateur doit fabriquer des adresses en écrivant le contenu du registre dans les emplacements de la pile et en vous donnant les adresses de ces emplacements de la pile. Ce faisant, le compilateur choisit, en un sens, les emplacements de la pile qui lui conviennent.

Commentaires (1)

Pourquoi les adresses de l'argc et de l'argv sont-elles séparées de 12 octets ?

Du point de vue de la norme linguistique, la réponse est "sans raison particulière". C ne spécifie ni n'implique aucune relation entre les adresses des paramètres de fonction. @EricPostpischil décrit ce qui se passe probablement dans votre implémentation particulière, mais ces détails seraient différents pour une implémentation dans laquelle tous les arguments sont passés sur la pile, et ce n'est pas la seule alternative.

De plus, j'ai du mal à trouver une façon dont ces informations pourraient être utiles dans un programme. Par exemple, même si vous "savez" que l'adresse de argv est 12 octets avant l'adresse de argc, il n'y a toujours pas de moyen défini pour calculer un de ces pointeurs à partir de l'autre.

Commentaires (19)