array - pointers significado
¿Debo usar char** argv o char*argv[] en C? (10)
Como acaba de aprender C, le recomiendo que realmente intente comprender las diferencias entre las matrices y los punteros primero en lugar de las cosas comunes .
En el área de parámetros y matrices, hay algunas reglas confusas que deberían ser claras antes de continuar. Primero, lo que declaras en una lista de parámetros se trata de manera especial. Hay situaciones en las que las cosas no tienen sentido como un parámetro de función en C. Estas son
- Funciones como parámetros
- Arrays como parámetros
Arrays como parámetros
El segundo quizás no esté inmediatamente claro. Pero queda claro cuando se considera que el tamaño de una dimensión de matriz forma parte del tipo en C (y una matriz cuyo tamaño de dimensión no se proporciona tiene un tipo incompleto). Por lo tanto, si crea una función que toma un valor por orden de matriz (recibe una copia), ¡podría hacerlo solo para un tamaño! Además, las matrices pueden volverse grandes y C intenta ser lo más rápido posible.
En C, por estos motivos, los valores de matriz no existen. Si desea obtener el valor de una matriz, lo que obtiene en su lugar es un puntero al primer elemento de esa matriz. Y aquí en realidad ya se encuentra la solución. En lugar de dibujar un parámetro de matriz no válido por adelantado, un compilador de C transformará el tipo del parámetro respectivo para que sea un puntero. Recuerda esto, es muy importante. El parámetro no será una matriz, sino que será un puntero al tipo de elemento respectivo.
Ahora, si intenta pasar una matriz, lo que se pasa es un puntero al primer elemento de la matriz.
Excursión: funciones como parámetros
Para completarlo, y porque creo que esto te ayudará a comprender mejor el asunto, veamos cuál es el estado de las cosas cuando tratas de tener una función como parámetro. De hecho, primero no tendrá ningún sentido. ¿Cómo puede un parámetro ser una función? Huh, queremos una variable en ese lugar, por supuesto! Entonces, lo que hace el compilador cuando eso sucede es, una vez más, transformar la función en un puntero de función . Intentar pasar una función pasará un puntero a esa función respectiva. Por lo tanto, los siguientes son los mismos (análogos al ejemplo de matriz):
void f(void g(void));
void f(void (*g)(void));
Tenga en cuenta que se necesitan paréntesis alrededor de *g
. De lo contrario, se especificaría una función que devuelve void*
, en lugar de un puntero a una función que devuelve void
.
De vuelta a las matrices
Ahora, dije al principio que las matrices pueden tener un tipo incompleto, lo que sucede si aún no se da un tamaño. Como ya calculamos que un parámetro de matriz no existe, sino que cualquier parámetro de matriz es un puntero, el tamaño de la matriz no importa. Eso significa que el compilador traducirá todo lo siguiente, y todos son lo mismo:
int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);
Por supuesto, no tiene mucho sentido ser capaz de poner cualquier tamaño en él, y simplemente se descarta. Por esa razón, C99 tuvo un nuevo significado para esos números, y permite que aparezcan otras cosas entre los corchetes:
// says: argv is a non-null pointer pointing to at least 5 char*''s
// allows CPU to pre-load some memory.
int main(int c, char *argv[static 5]);
// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);
// says the same as the previous one
int main(int c, char ** const argv);
Las últimas dos líneas dicen que no podrá cambiar "argv" dentro de la función, se ha convertido en un puntero const. Sin embargo, pocos compiladores C admiten esas características C99. Pero estas características dejan en claro que la "matriz" no es en realidad una. Es un puntero.
Una palabra de advertencia
Tenga en cuenta que todo lo que dije arriba es verdadero solo cuando tiene una matriz como parámetro de una función. Si trabaja con matrices locales, una matriz no será un puntero. Se comportará como un puntero, porque como se explicó anteriormente, una matriz se convertirá en un puntero cuando se lea su valor. Pero no se debe confundir con punteros.
Un ejemplo clásico es el siguiente:
char c[10];
char **c = &c; // does not work.
typedef char array[10];
array *pc = &c; // *does* work.
// same without typedef. Parens needed, because [...] has
// higher precedence than ''*''. Analogous to the function example above.
char (*array)[10] = &c;
Solo estoy aprendiendo C y me preguntaba cuál de estos debería usar en mi método principal. Hay alguna diferencia?
Editar: Entonces, ¿cuál es más común de usar?
No hace la diferencia, pero uso char *argv[]
porque muestra que es una matriz de tamaño fijo de cadenas de longitud variable (que generalmente son char *
).
No veo ningún mérito especial de utilizar cualquiera de los enfoques en lugar de utilizar el otro: utilice la convención más acorde con el resto de su código.
Puede usar cualquiera de las dos formas, ya que en las matrices C y los punteros son intercambiables en las listas de parámetros de función. Ver http://en.wikipedia.org/wiki/C_(programming_language)#Array-pointer_interchangeability .
Realmente no hace una diferencia, pero este último es más legible. Lo que se te da es una matriz de punteros de char, como dice la segunda versión. Sin embargo, se puede convertir implícitamente en un puntero de doble charla como en la primera versión.
Sé que esto está desactualizado, pero si solo está aprendiendo el lenguaje de programación C y no está haciendo nada importante con él, no use las opciones de línea de comandos.
Si no está utilizando argumentos de línea de comando, no use ninguno. Simplemente declare la función principal como int main()
si
- Desea que el usuario de su programa pueda arrastrar un archivo a su programa para que pueda cambiar el resultado de su programa con él o
- Desea manejar las opciones de la línea de comandos (
-help
,/?
O cualquier otra cosa que vaya después delprogram name
en la terminal o el símbolo del sistema)
usa el que tenga más sentido para ti. De lo contrario, solo use int main()
Después de todo, si termina queriendo agregar opciones de línea de comandos, puede editarlas fácilmente más tarde.
Si necesita una cantidad variable o dinámica de cadenas, es más fácil trabajar con char **. Sin embargo, si su número de serie es fijo, se preferiría char * var [].
char ** → puntero al puntero de carácter y char * argv [] significa una matriz de punteros de carácter. Como podemos usar puntero en lugar de una matriz, se pueden usar ambos.
debe declararlo como char *argv[]
, debido a todas las formas equivalentes de declararlo, que se acerca más a su significado intuitivo: una matriz de cadenas.
Podrías usar cualquiera, depende de cómo quieras usarlo. char* argv[]
es (en su mayoría) equivalente a char ** argv
.Ambas formas apuntan a punteros a char, la única diferencia es que con En realidad, estoy equivocado, son completamente equivalentes. Ver los comentarios de litb y su respuesta . char *argv[]
está informando al compilador que el valor de argv no cambiará (aunque los valores a los que apunta todavía pueden).
Realmente depende de cómo quiera usarlo (y podría usar cualquiera de los dos):
// echo-with-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char **argv)
{
while (--argc > 0)
{
printf("%s ", *++argv);
}
printf("/n");
return 0;
}
// echo-without-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
for (i=1; i<argc; i++)
{
printf("%s ", argv[i]);
}
printf("/n");
return 0;
}
En cuanto a cuál es más común, no importa. Cualquier programador de C experimentado que lea su código verá ambos como intercambiables (en las condiciones adecuadas). Al igual que un hablante de inglés experimentado lee "ellos son" y "ellos son" igualmente fácilmente.
Más importante es que aprenda a leerlos y reconocer cuán similares son. Leerá más código de lo que escribe, y deberá sentirse igualmente cómodo con ambos.