from - c++ terminal parameters
C++-char** argv vs. char*argv (7)
¿Cuál es la diferencia entre char** argv
y char* argv[]
? en int main(int argc, char** argv)
e int main(int argc, char* argv[])
?
¿Son lo mismo? Especialmente que la primera parte no tiene []
.
Ambos son iguales para su uso, excepto por las siguientes diferencias sutiles:
- Sizeof dará diferentes resultados para ambos
- Además, el segundo no se puede reasignar a una nueva área de memoria, ya que es una matriz
- Con el segundo solo puedes usar aquellos índices que son válidos. No está especificado por C / C ++ si intenta utilizar un índice de matriz más allá de la longitud de la matriz. Sin embargo, con char ** puedes usar cualquier índice de 0 a ...
- La segunda forma solo se puede utilizar como parámetros formales para una función. Mientras que primero se puede utilizar incluso para declarar variables dentro de una pila.
De hecho, son exactamente iguales.
La regla de oro de los arreglos para recordar es:
"El nombre de una matriz es un puntero al primer elemento de la matriz".
Así que si declara lo siguiente:
char text[] = "A string of characters.";
Luego, la variable "texto" es un puntero al primer carácter en la matriz de caracteres que acaba de declarar. En otras palabras, "texto" es de tipo char *
. Cuando accede a un elemento de una matriz utilizando [ índice ], lo que realmente está haciendo es agregar un desplazamiento de índice al puntero al primer elemento de la matriz y luego eliminar la referencia a este nuevo puntero. Las siguientes dos líneas, por lo tanto, inicializarán ambas variables a ''t'':
char thirdChar = text[3];
char thirdChar2 = *(text+3);
Usar los corchetes es una conveniencia proporcionada por el idioma que hace que el código sea mucho más legible. Pero la forma en que esto funciona es muy importante cuando empiezas a pensar en cosas más complejas, como los punteros a los punteros. char** argv
es lo mismo que char* argv[]
porque en el segundo caso "el nombre de la matriz es un puntero al primer elemento de la matriz".
De esto también debería poder ver por qué los índices de matriz comienzan desde 0. El puntero al primer elemento es el nombre de la variable de la matriz (regla de oro nuevamente) más un desplazamiento de ... ¡nada!
He tenido debates con un amigo mío sobre cuál es mejor usar aquí. Con la notación char* argv[]
puede ser más claro para el lector que esto es, de hecho, una "matriz de punteros a caracteres" en lugar de la notación char** argv
, que puede leerse como un "puntero a un puntero a un personaje". Mi opinión es que esta última notación no transmite tanta información al lector.
Es bueno saber que son exactamente iguales, pero para la lectura creo que si la intención es un conjunto de punteros, la notación char* argv[]
transmite esto mucho más claramente.
Hay una diferencia entre TYPE * NAME
y TYPE NAME[]
tanto en C como en C ++. En C ++ ambos tipos no son intercambiables. Por ejemplo, la siguiente función es ilegal (obtendrá un error) en C ++, pero legal en C (recibirá una advertencia):
int some (int *a[3]) // a is array of dimension 3 of pointers to int
{
return sizeof a;
}
int main ()
{
int x[3][3];
std::cout << some(x)<< std::endl;
return 0;
}
Para que sea legal, simplemente cambie la firma a int some (int (*a)[3])
(puntero a matriz de 3 ints) o int some (int a[][3])
. El número entre los últimos corchetes debe ser igual a un argumento. La conversión de una matriz de matrices a una matriz de punteros es ilegal. Convertir de puntero a puntero a matriz de arreglos también es ilegal. ¡Pero la conversión de puntero a puntero a un conjunto de punteros es legal!
Entonces recuerde: la firma más cercana al tipo de referencia no importa, otros sí lo hacen (en el contexto de los punteros y las matrices, claro).
Consideremos que tenemos un puntero a puntero a int:
int ** a;
&a -> a -> *a -> **a
(1) (2) (3) (4)
- No puede cambiar este valor, el tipo es
int ***
. Puede tomarse por función comoint **b[]
oint ***b
. Lo mejor esint *** const b
. - El tipo es
int **
. Puede tomarse por función comoint *b[]
oint ** b
. Los corchetes de la declaración de matriz pueden dejarse vacíos o contener cualquier número. - El tipo es
int *
. Puede tomarse por función comoint b[]
oint * b
o inclusovoid * b
- Debe tomarse como parámetro int. No quiero caer en detalles, como la llamada implícita del constructor.
Respondiendo a su pregunta: el tipo real de argumentos en la función principal es char ** argv
, por lo que puede representarse fácilmente como char *argv[]
(pero no como char (*argv)[]
). También se puede cambiar de safely nombre argv
de la función principal. Puede comprobarlo fácilmente: std::cout << typeid(argv).name();
(PPc = puntero a p. A char)
Por cierto: hay una característica genial, pasando matrices como referencias:
void somef(int (&arr)[3])
{
printf("%i", (sizeof arr)/(sizeof(int))); // will print 3!
}
Además, el puntero a cualquier cosa puede ser aceptado (convertido) implícitamente por función como puntero de vacío. Pero solo puntero único (no puntero a puntero, etc.).
Otras lecturas:
- Bjarne Stroustrup, C ++, capítulo 7.4
- Preguntas frecuentes sobre punteros C
La forma de corchete solo es útil en declaraciones de declaración como:
char *a[] = {"foo", "bar", "baz"};
printf("%d/n", sizeof a / sizeof *a);
// prints 3
Porque sabe en tiempo de compilación el tamaño de la matriz. Cuando se pasa una forma de corchete como parámetro a una función (principal o alguna otra), el compilador no tiene idea de cuál sería el tamaño de la matriz en tiempo de ejecución, por lo que es exactamente el mismo que char ** a. Prefiero char ** argv ya que es más claro que sizeof no funcionaría como lo haría en el formulario de declaración.
Para la primera parte de la pregunta:
- char ** argv: puntero a un puntero a un char
- char * argv []: puntero a una matriz
Entonces, la pregunta es si un puntero a un tipo C y una matriz C [] son las mismas cosas. En general, no son en absoluto, PERO son equivalentes cuando se usan en firmas .
En otras palabras, no hay diferencia en su ejemplo, pero es importante tener en cuenta la diferencia entre puntero y matriz de lo contrario.
Para todos los propósitos prácticos, son los mismos. Esto se debe al manejo de las matrices de C / C ++ pasadas como argumentos, donde una matriz decae a un puntero.
Son completamente equivalentes. char *argv[]
debe leerse como una matriz de punteros a char
y un argumento de matriz se reduce a un puntero, por lo que puntero a puntero a char
, o char **
.
Esto es lo mismo en C