Ho eseguito il seguente programma sul mio computer (Intel a 64 bit con Linux).
#include <stdio.h>
void test(int argc, char **argv) {
printf("[test] Argc Pointer: %p\n", &argc);
printf("[test] Argv Pointer: %p\n", &argv);
}
int main(int argc, char **argv) {
printf("Argc Pointer: %p\n", &argc);
printf("Argv Pointer: %p\n", &argv);
printf("Dimensione di &argc: %lu\n", sizeof (&argc));
printf("Dimensione di &argv: %lu\n", sizeof (&argv));
test(argc, argv);
ritorna 0;
}
L'output del programma era
-- lingua: nessuno -->
$ gcc size.c -o size
$ ./size
Puntatore Argc: 0x7fffd7000e4c
Puntatore Argv: 0x7fffd7000e40
Dimensione di &argc: 8
Dimensione di &argv: 8
[Test] Puntatore argc: 0x7fffd7000e2c
[test] Puntatore argv: 0x7fffd7000e20
La dimensione del puntatore &argv
è di 8 byte. Mi aspettavo che l'indirizzo di argc
fosse address of (argv) + sizeof (argv) = 0x7ffed1a4c9f0 + 0x8 = 0x7ffed1a4c9f8
ma c'è un padding di 4 byte in mezzo. Perché è questo il caso?
La mia ipotesi è che potrebbe essere dovuto all'allineamento della memoria, ma non ne sono sicuro.
Ho notato lo stesso comportamento anche con le funzioni che chiamo.
Sul vostro sistema, i primi pochi argomenti interi o puntatori sono passati in registri e non hanno indirizzi. Quando prendete i loro indirizzi con &argc
o &argv
, il compilatore deve fabbricare gli indirizzi scrivendo il contenuto del registro in posizioni dello stack e dandovi gli indirizzi di queste posizioni dello stack. Nel fare ciò, il compilatore sceglie, in un certo senso, qualsiasi posizione dello stack gli risulti conveniente.
Perché gli indirizzi di argc e argv sono distanti 12 byte?
Dal punto di vista dello standard del linguaggio, la risposta è "nessuna ragione particolare". Il C non specifica o implica alcuna relazione tra gli indirizzi dei parametri di funzione. @EricPostpischil descrive ciò che probabilmente sta accadendo nella vostra particolare implementazione, ma questi dettagli sarebbero diversi per un'implementazione in cui tutti gli argomenti sono passati sullo stack, e questa non è l'unica alternativa.
Inoltre, ho difficoltà a trovare un modo in cui tali informazioni potrebbero essere utili all'interno di un programma. Per esempio, anche se si "sa" che l'indirizzo di argv
è 12 byte prima dell'indirizzo di argc
, non c'è ancora un modo definito per calcolare uno di questi puntatori dall'altro.