Diferencia entre char ** p, char * p , char p

char *p = "some string" 

crea un puntero p que apunta a un bloque que contiene la cadena.

 char p[] = "some string" 

Crea una matriz de caracteres y con literales en ella.

Y la primera es una statement constante. ¿Es lo mismo de matrices bidimensionales?

Cuál es la diferencia entre

 char **p,char *p[],char p[][]. 

Leí un poco acerca de esto que char ** p crea una serie de punteros, por lo que tiene una sobrecarga en comparación con char p[][] para almacenar los valores del puntero.

Las dos primeras declaraciones crean arreglos constantes. No se produjo ningún error de tiempo de ejecución cuando intenté modificar el contenido de argv en main(int argc,char **argv) . ¿Es porque están declarados en función prototipo?

Declaraciones normales (no parámetros de función)

char **p; Declara un puntero a un puntero a char . Se reserva espacio para el puntero. No reserva ningún espacio para los punteros apuntados o cualquier char .

char *p[N]; Declara una matriz de N punteros a char . Se reserva espacio para N punteros. No reserva ningún espacio para cualquier char . N debe proporcionarse explícitamente o, en una definición con inicializadores, implícitamente permitiendo que el comstackdor cuente los inicializadores.

char p[M][N]; Declara un conjunto de matrices M de N char . Se reserva espacio para MN char . No hay punteros involucrados. M y N deben proporcionarse explícitamente o, en una definición con inicializadores, implícitamente permitiendo que el comstackdor cuente los inicializadores.

Declaraciones en Parámetros de Función

char **p declara un puntero a un puntero a char . Cuando se llama a la función, se proporciona espacio para ese puntero (normalmente en una stack o en un registro de procesador). No hay espacio reservado para los apuntadores a punteros o cualquier char .

char *p[N] se ajusta para ser char **p , por lo que es el mismo que el anterior. N se ignora y puede estar ausente.

char p[M][N] se ajusta para ser char (*p)[N] , por lo que es un puntero a una matriz de N char . M se ignora y puede estar ausente. N debe ser proporcionado. Cuando se llama a la función, se proporciona espacio para el puntero (normalmente en una stack o en un registro de procesador). No hay espacio reservado para la matriz de N char .

argv

argv es creado por el software especial que llama main . Está lleno de datos que el software obtiene del “entorno”. Se le permite modificar los datos de char en él.

En su definición char *p = "some string"; , no se le permite modificar los datos a los que apunta porque el estándar C indica que los caracteres en un literal de cadena no se pueden modificar. (Técnicamente, lo que dice es que no define el comportamiento si lo intentas). En esta definición, p no es una matriz; es un puntero al primer char en una matriz, y esos caracteres están dentro de una cadena literal, y no se le permite modificar el contenido de una cadena literal.

En su definición, char p[] = "some string"; , puede modificar los contenidos de p . No son una cadena literal. En este caso, la cadena literal no existe realmente en tiempo de ejecución; es solo algo utilizado para especificar cómo se inicializa la matriz p . Una vez que se inicializa p , puede modificarlo.

Los datos configurados para argv se configuran de una manera que le permite modificarlos (debido a que el estándar C lo especifica).

Alguna descripción más de diferencias mirando desde la vista de direccionamiento de memoria como sigue

I. char **p; p es doble puntero de tipo char

Declaración:

 char a = 'g'; char *b = &a; char **p = &b; 

  pba +------+ +------+ +------+ | | | | | | |0x2000|------------>|0x1000|------------>| g | | | | | | | +------+ +------+ +------+ 0x3000 0x2000 0x1000 Figure 1: Typical memory layout assumption 

En la statement anterior, a es a tipo char contiene un carácter g . El puntero b contiene la dirección de una variable de carácter existente a . Ahora b es la dirección 0x1000 y *b es el carácter g . Finalmente, la dirección de b se asigna a p , por lo tanto a es una variable de carácter, b es puntero y p es puntero a puntero. Lo que implica que a contiene a valor, b contiene la dirección p contiene la dirección de la dirección como se muestra a continuación en el diagtwig.

Aquí, sizeof(p) = sizeof(char *) en el sistema respectivo;

II. char *p[M]; p es un conjunto de cadenas

Declaración:

 char *p[] = {"Monday", "Tuesday", "Wednesday"}; 

  p +------+ | p[0] | +----------+ 0 | 0x100|------>| Monday\0 | | | +----------+ |------| 0x100 | p[1] | +-----------+ 1 | 0x200|------>| Tuesday\0 | | | +-----------+ |------| 0x200 | p[2] | +-------------+ 2 | 0x300|------>| Wednesday\0 | | | +-------------+ +------+ 0x300 Figure 2: Typical memory layout assumption 

En esta statement, p es una matriz de 3 punteros de tipo char . Implica que la matriz p puede contener 3 cadenas. Cada cadena (Monday, Tuesday & Wednesday) se encuentra en algún lugar de la memoria (0x100, 0x200 & 0x300) , las direcciones están en la matriz p como (p[0], p[1] & p[2]) respectivamente. De ahí que sea arsenal de punteros.

Notas: char *p[3];

 1. p[0], p[1] & p[2] are addresses of strings of type `char *`. 2. p, p+1 & p+2 are address of address with type being `char **`. 3. Accessing elements is through, p[i][j] is char; p[i] is char *; & p is char ** 

Aquí sizeof(p) = Number of char array * sizeof(char *)

III. char p[M][N]; p es una matriz de cadenas de longitud fija con dimensiones como M x N

Declaración:

 char p[][10] = {Monday, Tuesday, Wednesday}; 

  p 0x1 2 3 4 5 6 7 8 9 10 +-------------------------+ 0 | M onday \0 \0 \0 \0| 1 | T uesday \0 \0 \0| 2 | W ednesday \0| +-------------------------+ Figure 3: Typical memory layout assumption 

En este caso, la matriz p contiene 3 cadenas, cada una con 10 caracteres. Desde el diseño de la memoria, podemos decir que p es una matriz bidimensional de caracteres con tamaño MxN , que es 3x10 en nuestro ejemplo. Esto es útil para representar cadenas de igual longitud, ya que existe la posibilidad de desperdicio de memoria cuando las cadenas contienen menos de 10 caracteres en comparación con la statement char *p[] , que no tiene desperdicio de memoria porque la longitud de la cadena no se especifica y es útil para representar cuerdas de longitud desigual.

El acceso a los elementos es similar al caso anterior, p[M] es la cadena M’th & p [M] [N] es el número N de la cadena M’th. Aquí sizeof(p) = (M rows * N columns) * sizeof(char) de una matriz bidimensional;

  • a in char* a es char* a puntero a la matriz de caracteres, a puede ser modificado.
  • b en char b[] es un conjunto de caracteres. b no puede ser modificado.

Son de a tipo compatibles: b puede descomponerse automáticamente en a en asignaciones y expresiones, pero no al revés.

Cuando usas char** p , char* p[] y char p[][] es una situación muy similar, solo más niveles de direccionamiento indirecto.