Ejecuté el siguiente programa en mi computadora (Intel de 64 bits 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("Size of &argc: %lu\n", sizeof (&argc)); printf("Size of &argv: %lu\n", sizeof (&argv)); test(argc, argv); return 0; }
El resultado del programa fue
$ gcc size.c -o size $ ./size Argc Pointer: 0x7fffd7000e4c Argv Pointer: 0x7fffd7000e40 Size of &argc: 8 Size of &argv: 8 [test] Argc Pointer: 0x7fffd7000e2c [test] Argv Pointer: 0x7fffd7000e20
El tamaño del puntero &argv
es de 8 bytes. Esperaba que la dirección de argc
fuera address of (argv) + sizeof (argv) = 0x7ffed1a4c9f0 + 0x8 = 0x7ffed1a4c9f8
pero hay un relleno de 4 bytes entre ellos. ¿Por qué es este el caso?
Supongo que podría deberse a la alineación de la memoria, pero no estoy seguro.
También noto el mismo comportamiento con las funciones a las que llamo.
En su sistema, los primeros argumentos enteros o punteros se pasan en registros y no tienen direcciones. Cuando toma sus direcciones con &argc
o &argv
, el compilador tiene que fabricar direcciones escribiendo el contenido del registro en las ubicaciones de la pila y brindándole las direcciones de esas ubicaciones de la pila. Al hacerlo, el compilador elige, en cierto sentido, cualquier ubicación de la pila que le resulte conveniente.
¿Por qué las direcciones de argc y argv están separadas por 12 bytes?
Desde la perspectiva del estándar lingüístico, la respuesta es "ninguna razón en particular". C no especifica ni implica ninguna relación entre las direcciones de los parámetros de función. @EricPostpischil describe lo que probablemente sucede en su implementación particular, pero esos detalles serían diferentes para una implementación en la que todos los argumentos se pasan a la pila, y esa no es la única alternativa.
Además, tengo problemas para encontrar una forma en que dicha información pueda ser útil dentro de un programa. Por ejemplo, incluso si "sabe" que la dirección de argv
está 12 bytes antes que la dirección de argc
, todavía no hay una forma definida de calcular uno de esos punteros a partir del otro.