por - para que sirve int argc char*argv[]
¿Cuándo puede argv[0] tener nulo? (4)
De acuerdo con esta lista de correo , argv[0]
puede ser nulo si argc == 0
. Pero no explican cuándo argc
puede ser cero. Yo sospecharía que argc
sería cero en situaciones donde un ejecutable no se lanzó "normalmente" (es decir, a través de una línea de comandos, popen
, etc.) - y de hecho, como se mencionó en @paxdiablo, puede establecer manualmente argv
con la familia exec
de funciones , por lo que argc
podría ser cero dependiendo de esos argumentos.
Pero, en su sección de Justificación :
Las primeras propuestas requerían que el valor de
argc
pasado amain()
sea "uno o mayor". Esto fue impulsado por el mismo requisito en los borradores de la norma ISO C. De hecho, las implementaciones históricas han pasado un valor de cero cuando no se proporcionan argumentos al llamador de las funciones exec. Este requisito se eliminó de la norma ISO C y, posteriormente, también se eliminó de este volumen de IEEE Std 1003.1-2001. La redacción, en particular el uso de la palabra debería, requiere que una Aplicación POSIX Estrictamente Conforme pase al menos un argumento a la función exec, garantizando así queargc
sea uno o mayor cuando sea invocado por dicha aplicación. De hecho, esta es una buena práctica, ya que muchas aplicaciones existentes hacen referencia aargv[0]
sin verificar primero el valor deargc
.
Así que ahí lo tienen: las aplicaciones POSIX estrictamente conformes deben tener argc
mayor que cero, pero eso no está garantizado de ninguna manera.
Hay un poco más de información sobre el estándar con respecto a argc
y argv
en la sección Inicio del programa .
Lo que entiendo acerca de pasar argumentos a main () desde la línea de comando es que argc tiene un valor mínimo de 1 y argv [0] siempre tendrá el nombre del programa con su ruta.
Si se proporcionan argumentos en la línea de comando, argc tendrá un valor mayor que uno y argv 1 a argv [argc-1] tendrá esos argumentos.
Ahora un párrafo en 1 dice que
argv [0] será una cadena que contenga el nombre del programa o una cadena nula si no está disponible.
Ahora, ¿cómo y cuándo puede argv [0] tener una cadena nula? Quiero decir que el nombre del programa con su ruta siempre estará disponible, así que ¿cuándo puede ser nulo?
El escritor dice que "si eso no está disponible", pero ¿cuándo y cómo es posible que el nombre del programa no esté disponible?
Es posible imaginar plataformas donde los programas no tienen nombres, tal vez el código simplemente se carga al inicio. En esos, argv [0] podría suponer que es NULL. El estándar C ciertamente permite un valor argc de cero, y dice que argv [argc] será NULL.
Ejemplo POSIX ejecutable
ac
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
char *argv[] = {NULL};
char *envp[] = {NULL};
execve("b.out", argv, envp);
}
bc
#include <stdio.h>
int main(int argc, char **argv) {
if (argc == 0 && argv[0] == NULL)
puts("yup");
}
Entonces:
gcc a.c -o a.out
gcc b.c -o b.out
./a.out
Da:
yup
Probado en Ubuntu 16.10.
Probar el programa existente con la lista de argumentos vacía
Aquí hay una envoltura que toma una ruta como argumento y la ejecuta como un comando sin argumentos:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char**argv) {
char *empty[] = {NULL};
execve(argv[1], empty, empty);
perror("empty-args: execve failed"); // Bad Address (EFAULT) if our argv[1] == NULL
return 1;
}
uso:
./empty-args ./arg-count
Con la clase de llamadas exec
, especifique el nombre del programa y el ejecutable del programa por separado, de modo que pueda establecerlo en NULL.
Pero esa cita es en realidad del estándar ISO (posiblemente parafraseado) y ese estándar cubre una amplia gama de entornos de ejecución, desde el microcontrolador más pequeño hasta el último mainframe de clase empresarial z10.
Muchos de esos sistemas integrados estarían en la situación donde un nombre ejecutable tiene poco sentido.
Desde el último borrador de c1x:
El valor de
argc
será no negativo.El valor
argv[argc]
será un puntero nulo.Si el valor de
argc
es mayor que cero, los miembros de la matrizargv[0]
través deargv[argc-1]
inclusive contendrán punteros a cadenas, a los que el entorno de host proporciona valores definidos por la implementación antes del inicio del programa.
Esto significa que, si argc
es cero (y puede ser), argv [0] es NULL.
Pero, incluso cuando argc
no es 0, es posible que no obtenga el nombre del programa, ya que el estándar también establece:
Si el valor de
argc
es mayor que cero, la cadena apuntada porargv[0]
representa el nombre del programa;argv[0][0]
será el carácter nulo si el nombre del programa no está disponible en el entorno host. Si el valor deargc
es mayor que uno, las cadenas apuntadas porargv[1]
través deargv[argc-1]
representan los parámetros del programa.
Por lo tanto, no hay ningún requisito bajo la norma de que se proporcione un nombre de programa. He visto que los programas utilizan una amplia selección de opciones para este valor:
- Sin valor en absoluto (por supuesta seguridad).
- una mentira descarada (como
sleep
por un código malicioso). - el nombre real del programa (como
sleep
). - uno ligeramente modificado (como
-ksh
para el shell de inicio de sesión). - un nombre descriptivo (por ejemplo,
progname - a program for something
).