Diferencia entre char *argv[] y char **argv para el segundo argumento de main() [duplicate]

7 minutos de lectura

Diferencia entre char argv y char argv para el segundo
jhansi rani

CÓDIGO 1

#include<stdio.h>

int main(int argc, char *argv[])
{
int j;
printf("%d", argv[1][0]);
return 0;
}

CÓDIGO 2

#include<stdio.h>

int main(int argc, char **argv)
{
int j;
printf("%d", argv[1][0]);
return 0;
}

CÓDIGO 1 y CÓDIGO 2 ambos dan la misma salida. pero argumento 2 de la función principal en CÓDIGO 1 y CÓDIGO 2 son diferentes. Se crea una matriz de punteros sobre la sección de datos en el momento de la compilación. argv es una matriz de punteros. Entonces deberíamos declarar el argumento en la función principal como puntero a puntero a carácter, es decir, **argv. ¿Cómo es correcto declarar como en el CÓDIGO 1?

  • El segundo parámetro no es diferente de ninguna manera en lo que respecta al compilador, es decir char *argv[] es simplemente equivalente a char **argv. Eso es más como una cuestión de estilo de codificación preferido.

    -Grzegorz Szpetkowski

    30 de noviembre de 2014 a las 13:23


Diferencia entre char argv y char argv para el segundo
bmargulies

Es fundamental para c que char** x y char* x[] son dos formas de expresar la misma cosa. Ambos declaran que el parámetro recibe un puntero a una matriz de punteros. Recuerda que siempre puedes escribir:

 char *parray[100];
 char **x;

 x = &parray[0];

y luego use x de manera idéntica.

  • Aparte del uso de sizeof

    – Ed Heal

    30 de noviembre de 2014 a las 13:32

  • En mi opinión, esta respuesta mejoraría significativamente si al menos notara brevemente que hay algunos lugares en C (como el sizeof mencionado por Ed Heal) donde las matrices son no equivalente a punteros, y que el “ajuste de matriz” en las declaraciones de parámetros de función (sobre las que pregunta la pregunta) es distinto (aunque relacionado con) el “decaimiento de matriz” en las expresiones. Para referencias, podría citar, por ejemplo, ¿Cuál es un término moderno para “equivalencia de matriz/puntero”? y ¿Excepción a la matriz que no se descompone en un puntero?

    – Ilmari Karonen

    14 de marzo de 2018 a las 12:55


  • @ Ilmari-Karonen En mi humilde opinión, esta respuesta es correcta (sin embargo, el ejemplo es incorrecto). ¡Solo porque hay llaves en la firma de una función, no significa que será una variable de matriz! ¡La verdad es que C asume que es un puntero normal! Esa es incluso la única decisión lógica que uno podría esperar de C, ya que si REALMENTE se supusiera una variable de matriz, no se le podría asignar nada (la variable de matriz no tiene memoria separada específica para sí misma como lo hacen los punteros). Entonces creo que esto es solo una notación simplificadora (charArr[]) proporcionado por C, que es exactamente lo mismo que la otra notación (char*arr).

    – aderchox

    20 de noviembre de 2018 a las 9:57

Básicamente, char* argv[] significa matriz de punteros char, mientras que char** argv significa puntero a un puntero char.

En cualquier matriz, el nombre de la matriz es un puntero al primer elemento de la matriz, es decir, contiene la dirección del primer elemento.

Entonces, en el código que se proporciona a continuación, en la matriz de caracteres x, x es un puntero al primer elemento, ‘1’, que es un carácter. Entonces es un puntero a un personaje.

Y en el arreglo arr, arr es el primer elemento del puntero, x, que en sí mismo es un puntero a un carácter. Así que es un puntero a otro puntero.

Por lo tanto, x es char* y arr es char**.

Al recibir algo en una función, la regla básica es que debe indicar el tipo de lo que está recibiendo. Así que simplemente dices que quieres recibir un char**, o también puedes decir char* arr[].

En el primer caso, no necesitamos pensar nada complejo. Simplemente sabemos que estamos recibiendo una matriz de char*. ¿No sabemos esto? Entonces, lo recibimos y lo usamos.

En el segundo caso, es simple, como expliqué anteriormente que arr es un char **, puede poner esto como su tipo y recibirlo de manera segura. Ahora que el sistema conoce el tipo de cosas que hemos recibido, podemos acceder a los siguientes elementos simplemente usando la anotación de matriz. Es como si recibimos la dirección de inicio de la matriz, seguramente podemos ir a los siguientes elementos y, como sabemos su tipo, sabemos qué contiene y cómo podemos usarlo más. Sabemos que contiene un puntero a char, por lo que también podemos acceder a ellos legalmente.

void func1(char* arr[])
{
    //function body
}
void func2(char** arr)
{
    //function body
}

int main()
{
    //x, y and z are pointer to char
    char x[3]={'1', '2', '3'};
    char y[3]={'4', '5', '6'};
    char z[3]={'7', '8', '9'};

    //arr is pointer to char pointer
    char* arr[3]={x, y, z};

    func1(arr);
    func2(arr);
}

  • Hay una serie de conceptos erróneos en esta respuesta, que ya han confundido al menos a una persona. En primer lugar, char* argv[] y char** argv son absolutamente equivalentes y no significan cosas diferentes en absoluto. En segundo lugar, arr es no un puntero No estudié el texto lo suficientemente cerca como para identificar otros problemas específicos, pero esos ya son serios como para justificar un voto negativo y una sincera esperanza de que vuelvas a leer esta publicación antes de que otros sean engañados.

    – Carreras de ligereza en órbita

    2 de marzo de 2018 a las 18:54


  • (absolutamente equivalente en este contextopor lo menos)

    – Carreras de ligereza en órbita

    02/03/2018 a las 19:00

  • @LightnessRacesinOrbit Re: En segundo lugar, arr no es un puntero – tal vez comente qué arr es y cual arr – Veo varios usos en esta respuesta.

    – chux – Reincorporar a Monica

    02/03/2018 a las 19:30

  • @chux: Buen punto. ¡Estaba respondiendo al comentario del código y olvidé decirlo!

    – Carreras de ligereza en órbita

    02/03/2018 a las 19:34

  • ¡Estoy de acuerdo en que esta respuesta es engañosa! Por un lado, el nombre de la matriz NO es un puntero. Es la “dirección” del primer elemento del arreglo, ¡no lo CONTIENE! ¡Ya que no tiene una ubicación separada en la memoria! Corrija estos errores o elimine la respuesta.

    – aderchox

    20 de noviembre de 2018 a las 9:36

Son exactamente iguales. §5.1.2.2.2 del estándar C11 establece:

La función llamada al inicio del programa se llama main. La implementación no declara ningún prototipo para esta función. Se definirá con un tipo de retorno de int y sin parámetros:

int main(void) { /* ... */ }

o con dos parámetros (referidos aquí como argc y argvaunque se puede usar cualquier nombre, ya que son locales a la función en la que se declaran):

int main(int argc, char *argv[]) { /* ... */ }

o equivalente;10) o de alguna otra manera definida por la implementación.

10) Así, int puede ser reemplazado por un nombre typedef definido como into el tipo de argv Se puede escribir como char ** argvy así.

Claramente, la intención es que ambas declaraciones sean idénticas. Además de eso, la regla se describe en §6.7.6.3/7:

Una declaración de un parámetro como ”matriz de escribe” se ajustará a ” puntero calificado para
escribe”, donde los calificadores de tipo (si los hay) son los especificados en el [ and ] de la derivación del tipo matriz. …

1647577871 498 Diferencia entre char argv y char argv para el segundo
jde-chil

[EDIT] Usando GCC en el momento del comentario probablemente GCC 7.2

declarando una matriz como esta

char array[]

lo hace constante, lo que significa que NO PUEDE tener el siguiente código

char array[] = "hello";
array = "hey";

a pesar de que la segunda cadena es más pequeña y debería caber, obtienes este error

error: tipo de matriz ‘char [6]’ no es asignable

si usted tiene **argv puedes escribir

main(int argc, char **argv)
{
    char **other_array;
    /*
     * do stuff with other_array
     */
    argv = other_array;
}

si usted tiene *argv[] luego

main(int argc, char *argv[])
{
    char **other_array;
    /*
     * do stuff with other_array
     */
    argv = other_array;
}

te da esta advertencia

advertencia: la asignación a ‘const char **’ desde ‘char **’ descarta calificadores en tipos de punteros anidados

por lo que técnicamente es una pequeña optimización como si hubieras escrito const

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad