2011-07-21 15 views
5

Si uso Char *s[], que puede hacer lo siguiente:char ** s frente a char * s [], ¿cuándo y cómo usar cada uno?

char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"}; 

¿Cuál es la diferencia con **s? ¿Cómo utilizo el char **s en lugar de char *s[] en ese caso?

Ejemplo: int main (int argc, char **argv) en lugar de *argv[]

+0

s/"john /" john "?? – hari

+0

Marcelo, no olvide marcar una respuesta como aceptada si resolvió el problema o pedir más aclaraciones. – sidyll

Respuesta

0

Desde mi conocimiento, ** s es la dirección de la dirección de s, donde s * [] es la dirección de la matriz s, creo que sería almacenar valores individuales en s, pero en s [] almacenaría matriz, y la matriz en sí misma es un puntero. ¡Espero que esto ayude!

+0

Nah, para el doble puntero podría almacenar un solo valor, pero es más probable que sea un bloque de datos o un bloque de punteros que apuntan a los bloques – alternative

+0

Quise decir que apunta a la matriz, no esa matriz es el puntero, mi mal en eso. – Grigor

7

Para los parámetros de función, no hay diferencia.

De lo contrario:

char *s[]; 

s es una matriz de puntero a char. Y

char **s; 

s es un puntero a puntero a char.

Utiliza la primera si necesitas una matriz de puntero a char, y la utilizas si necesitas un puntero a un puntero a una char.

0

Si define

char **s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"}; 

creo que es la misma como la definición de matrices tridiensional (char s [10] [10] [10]), ya que char * s [] es la definición de una matriz bidimensional.

1

Crean la misma estructura de datos. La única diferencia es que char * s [] malloca automáticamente suficiente memoria para {"foo", "bar", "foobar", "whatever", "john, "doe"} al inicializarse. char ** s solo asignaría un byte para el puntero, entonces usted debería mallocar manualmente la memoria para cada cadena en la matriz.

0

cuando usa char *s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"}; el compilador ya conoce la longitud de la matriz, es decir: en este caso, sabe que es un puntero a punteros de 6 matrices de caracteres.

char** carece de la información de longitud y eso es específicamente por qué principal tiene 2 argumentos {length, pointer to pointer to char} == {argc, arv}

2

Como parámetros de la función, no hay ninguna diferencia en absoluto. Ellos son equivalentes.

void f(int** p); 
void f(int* p[]); 
void f(int* p[42]); 

Estas tres declaraciones son equivalentes.

Como objetos, tienen diferentes tipos;

char *s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"}; 

s es una matriz de 6 punteros a charsizeof(s) == 6*sizeof(void*)

char **s; 

s es un puntero a puntero a char. sizeof(s) == sizeof(void*)

+0

+ 1 para una respuesta concisa. Minit nit (no debería marcar la diferencia): debería usar 'sizeof (char *)' en lugar de 'void *'. – tomlogic

+1

@tomlogic: estoy usando 'void *' para enfatizar que todos los punteros tienen el mismo tamaño y uno es un puntero y el otro es una matriz de punteros (no importa qué punteros). –

+0

@Armen: no exactamente: http: // stackover flow.com/questions/1241205/are-all-data-pointers-of-the-same-size-in-one-platform. Aún así, 'char *' y 'void *' tienen el mismo tamaño y representación. –

1

Arrays y punteros son cosas diferentes. Un puntero se puede usar para acceder a un elemento en la matriz. Para poder inicializar una matriz, necesita declarar una matriz, no un puntero.

Para mostrar con claridad la diferencia intente esto:

int[] ia = {1, 2, 3, 4, 5, 6, 7, 8}; 
int* ip = ia; 

printf("sizeof(ia): %zu, sizeof(ip): %zu", sizeof(ia), sizeof(ip)); 

El primero debe imprimir el tamaño de la matriz, el segundo el tamaño de un puntero int.

Lo curioso de C es que cuando una matriz se pasa como parámetro de una función, se descompone en un puntero. Ver más en la sección 2.3 de http://www.lysator.liu.se/c/c-faq/c-2.html. La razón principal acepta argv** en lugar de argv*[] es que argv*[] se descompone en argv** cuando se pasa como parámetro de función.

1

respuesta no directamente a su Que pero esto podría ayudar a entender un poco más:

#include <stdio.h> 
#include <string.h> 

int main() { 

    char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"}; 

    printf(" s[0]: %s \n", s[0]); 
    printf(" *s: %s \n", *s); 
    printf(" *s+1: %s \n", *s+1); 
    printf("*(s+1): %s \n", *(s+1)); 

return 0; 
} 

Salida:

$ gcc -o chararr chararr.c 
$ ./chararr 
    s[0]: foo 
    *s: foo 
    *s+1: oo 
*(s+1): bar 
0

Depende de sus necesidades. Si el programa no tiene que modificar estas cadenas más tarde se puede utilizar

char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"}; 

Estos son compilados como literales de cadena única sección de leer.

salida de Asamblea:

 .file "test.c" 
     .section  .rodata 
.LC0: 
     .string "foo" 
.LC1: 
     .string "bar" 
.LC2: 
     .string "foobar" 
.LC3: 
     .string "whatever" 
.LC4: 
     .string "john" 
.LC5: 
     .string "doe" 
     .text 

Si intenta modificar estas cadenas más tarde en el programa que obtendría un fallo de segmentación. En ese caso, tiene que usar char **s

+0

¿Cómo se asignan (es decir, 6) palabras con char ** s? –