2011-03-04 38 views
37

¿Cuál es la diferencia entre char** argv y char* argv[]? en int main(int argc, char** argv) y int main(int argc, char* argv[])?C++ - char ** argv vs char * argv []

¿Son lo mismo? Especialmente que la primera parte no tiene [].

Respuesta

45

Son totalmente equivalentes. char *argv[] debe leerse como un array de punteros a char y un argumento de matriz se degrada a un puntero, por lo puntero a puntero a char o char **.

Esta es la misma en C.

+0

Gracias por su respuesta. ¿Puede explicar esto más: '... y un argumento de matriz se degrada a un puntero, por lo que apunta a puntero a char, o char **.' – Simplicity

+4

@user: Es una regla de idioma. Cuando declaras o defines una función con la sintaxis 'X foo (Y a [])', entonces realmente se convierte en 'X foo (Y * a)'. Lo que parece un argumento de matriz para una función es realmente un puntero. Como 'argv' se declara como una matriz (de punteros), se convierte en un puntero (a punteros). –

+0

La parte * puntero a char * es clara para 'char ** argv'. Pero, ¿de dónde viene el primer puntero? – Simplicity

3

Para todos los propósitos prácticos, son lo mismo. Esto se debe a que C/C++ maneja las matrices pasadas como argumentos, donde una matriz se desintegra a un puntero.

3

Para la primera parte de la pregunta: ¿

  • char ** argv: puntero a un puntero a un char
  • char * argv []: puntero a una matriz

Así la pregunta es si un puntero a un tipo C y un conjunto C [] son ​​las mismas cosas. No son para nada en general, PERO son equivalent when used in signatures.

En otras palabras, no hay ninguna diferencia en su ejemplo, pero es importante tener en cuenta la diferencia entre el puntero y la matriz de otra manera.

+0

El enlace es a C Preguntas frecuentes, pero la pregunta está etiquetada C++. –

+1

C++ es una extensión de C ... Entonces todo lo que se aplica a C es relevante para C++. –

+1

No. Hay pensamientos ilegales en C y permitidos en C++, por lo que cuando una fuente dice "es ilegal ..." no significa que esto se aplique a C++. – Mephane

17

De hecho, son exactamente lo mismo.

La regla de oro de las matrices que debe recordar es:

"El nombre de un array es un puntero al primer elemento de la matriz."

Así que si declaramos lo siguiente:

char text[] = "A string of characters.";

A continuación, el "texto" variable es un puntero al primer carácter en el conjunto de caracteres que acaba declarado. En otras palabras, "texto" es del tipo char *. Cuando accede a un elemento de una matriz usando [índice], lo que realmente está haciendo es agregar una compensación de índice al puntero al primer elemento de la matriz y luego quitarle la referencia a este nuevo puntero. Por lo tanto, las siguientes dos líneas inicializará ambas variables en 't':

char thirdChar = string[3]; 
char thirdChar2 = *(string+3); 

El uso de los corchetes es una conveniencia proporcionada por el lenguaje que hace que el código sea más legible. Pero la forma en que esto funciona es muy importante cuando comienzas a pensar en cosas más complejas, como punteros a punteros. char** argv es la misma 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 debe ser capaz de ver por qué es que los índices de matriz comienzan desde 0.El puntero al primer elemento es el nombre de la variable de la matriz (regla de oro otra vez) más un desplazamiento de ... ¡nada!

He tenido debates con un amigo 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 oposición a la notación char** argv que puede leerse como un "puntero a un puntero a un carácter". Mi opinión es que esta última notación no transmite tanta información al lector.

Es bueno saber que son exactamente lo mismo, pero para readablity creo que si la intención es una matriz de punteros, la notación char* argv[] transmite esto mucho más claramente.

+0

Gracias por su respuesta. ¿Puedes decirme cómo son las dos formas iguales? – Simplicity

+0

He editado mi respuesta, que debería dar una explicación más detallada. –

+0

+1 para corchetes –

-2

Ambos son igual para su uso excepto por las siguientes diferencias sutiles:

  • Sizeof dará resultados diferentes para ambos
  • Además segunda no puede ser reasignado a una nueva área de memoria, ya que es una matriz
  • Con el segundo, puede usar solo los índices que son válidos. No está especificado por C/C++ si intenta usar un índice de matriz más allá de longitud de matriz. Sin embargo, con char ** puede usar cualquier índice de 0 a ...
  • El segundo formulario solo se puede usar como parámetros formales para una función. Mientras que primero se puede usar para declarar variables dentro de una pila.
+2

¿Qué? En el contexto en el que OP está preguntando, cada uno de estos es incorerct. –

2

La forma del soporte sólo es útil en las declaraciones declaración como:

char *a[] = {"foo", "bar", "baz"}; 
printf("%d\n", sizeof a/sizeof *a); 
// prints 3 

Debido a que sabe en tiempo de compilación el tamaño de la matriz. Cuando pasa un formulario de paréntesis como parámetro a una función (principal o alguna otra), el compilador no tiene idea de cuál será el tamaño de la matriz en tiempo de ejecución, por lo que es exactamente lo 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 de estado de cuenta.

-1

Hay una diferencia entre TYPE * NAME y TYPE NAME[] tanto en C como en C++. En C++ ambos tipos no son intercables. Por ejemplo siguiente función es ilegal (obtendrá un error) en C++, pero legal en C (obtendrá la 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 sólo cambia la firma de int some (int (*a)[3]) (puntero a la matriz de 3 enteros) o int some (int a[][3]). El número en los últimos corchetes debe ser igual a un argumento. La conversión de una matriz de matrices a una matriz de punteros es ilegal. La conversión de puntero a puntero a una matriz de matrices también es ilegal. ¡Pero convertir el puntero a puntero en una matriz de punteros es legal!

Así que recuerde: La firma más cercana al tipo de desreferencia no importa, otros hacen (en el contexto de punteros y matrices, claro).

Considere como tenemos un puntero a puntero a int:

int ** a; 
&a  ->  a -> *a -> **a 
(1)   (2)   (3)   (4) 
  1. No se puede cambiar este valor, el tipo es int ***. Puede tomarse por función como int **b[] o int ***b. Lo mejor es int *** const b.
  2. El tipo es int **. Puede tomarse por función como int *b[] o int ** b. Los corchetes de la declaración de matriz pueden dejarse vacíos o contener cualquier número.
  3. El tipo es int *. Puede tomarse por función como int b[] o int * b o incluso void * b
  4. Debe tomarse como parámetro int. No quiero caer en detalles, como una llamada de constructor implícita.

Respondiendo su pregunta: el tipo real de argumets en función principal eschar ** argv, por lo que puede ser fácilmente representado como char *argv[] (pero no tan char (*argv)[]). También argv nombre de la función principal puede ser safely cambiado. Usted puede comprobar fácilmente: std::cout << typeid(argv).name(); (PPC = puntero a p a char.)

Por cierto: hay una característica interesante, pasar matrices como referencias:

void somef(int (&arr)[3]) 
{ 
    printf("%i", (sizeof arr)/(sizeof(int))); // will print 3! 
} 

Además puntero a nada puede ser implícitamente aceptado (convertido) por la función como puntero de vacío. Pero solo un puntero único (no puntero a puntero, etc.).

bibliográficas:

  1. Bjarne Stroustrup, C++, capítulo 7.4
  2. C pointers FAQ
+0

_ "Hay una diferencia entre TYPE * NAME y TYPE NAME [] en C y C++." _ Tonterías. _ "En C++ ambos tipos no son intercables". _ No, solo el primer tipo realmente existe. _ "Por ejemplo, la siguiente función es ilegal (obtendrá un error)" _ Eso es porque 'int * ar [3]' y 'int * ar []' son cosas completamente diferentes. La desinformación sigue y sigue ... –

+0

¿Qué significa 'clothest'? – Dan

+0

@Dan quise decir más cercano, lo siento – yanpas