pointer examples ejemplos define convert bidimensional array c arrays pointers arrayofarrays

examples - ¿Cuál es la diferencia entre las definiciones de matriz char*str={"foo",...} y char str[][5]={"foo",...}?



pointer c (9)

Caso 1:

Cuando yo escribo

char*str={"what","is","this"};

luego str[i]="newstring"; es válido mientras que str[i][j]=''j''; es inválido.

Parte II
>> char*str={"what","is","this"};

En esta declaración, str es un puntero al tipo de caracteres. Al compilar, debe recibir un mensaje de advertencia en esta declaración:

warning: excess elements in scalar initializer char*str={"what","is","this"}; ^

La razón de la advertencia es: usted está proporcionando más de un inicializador a un escalar.
[Los tipos aritméticos y los tipos de punteros se denominan colectivamente tipos escalares. ]

str es un escalar y de C Standards # 6.7.9p11 :

El inicializador para un escalar debe ser una sola expresión, opcionalmente encerrado entre llaves. ..

Además, dar más de un inicializador a un escalar es un comportamiento indefinido .
De C Standards # J.2 Comportamiento indefinido :

El inicializador para un escalar no es una sola expresión ni una sola expresión entre llaves

Dado que es un comportamiento indefinido según el estándar, no tiene sentido seguir discutiéndolo . Discutiendo la Parte I.II y la Parte I.III con una suposición - char *str="somestring" , solo para una mejor comprensión del tipo char * .
Parece que quiere crear una matriz de punteros a cadena. He agregado un breve sobre el conjunto de punteros a la cadena, a continuación en esta publicación, después de hablar sobre ambos casos.

Parte I.II
>> then str[i]="newstring"; is valid

No , esto no es válido
Nuevamente, el compilador debe estar dando un mensaje de advertencia en esta declaración debido a una conversión incompatible.
Dado que str es un puntero al tipo de caracteres. Por lo tanto, str[i] es un personaje en i coloca más allá del objeto al que apunta str [ str[i] --> *(str + i) ].

"newstring" es un literal de cadena y un literal de cadena decae en un puntero, excepto cuando se usa para inicializar una matriz, de tipo char * y aquí está tratando de asignarlo a un tipo de char . De ahí que el compilador lo informe como una advertencia.

Parte I.III
>> whereas str[i][j]=''j''; is invalid.

Sí, esto no es válido.
El [] (operador de subíndice) puede usarse con arreglos o operandos de puntero.
str[i] es un personaje y str[i][j] significa que estás usando [] en el operando char que no es válido. De ahí que el compilador lo informe como un error.

Caso 2

Cuando yo escribo

char str[][5]={"what","is","this"};

luego str[i]="newstring"; no es válido, mientras que str[i][j]=''J''; es válida.

Parte II.I
>> char str[][5]={"what","is","this"};

Esto es absolutamente correcto. Aquí, str es una matriz 2D. En función del número de inicializadores, el compilador establecerá automáticamente la primera dimensión. La vista en memoria de str[][5] , en este caso, sería algo como esto:

str +-+-+-+-+-+ str[0] |w|h|a|t|0| +-+-+-+-+-+ str[1] |i|s|0|0|0| +-+-+-+-+-+ str[2] |t|h|i|s|0| +-+-+-+-+-+

Según la lista de inicializadores, los elementos respectivos de 2D-array se inicializarán y el resto de los elementos se establecerán en 0 .

Parte II.II
>> then str[i]="newstring"; is not valid

Sí, esto no es válido.
str[i] es una matriz unidimensional.
Según los Estándares C, una matriz no es un valor l modificable.
De C Estándares # 6.3.2.1p1 :

Un lvalue es una expresión (con un tipo de objeto distinto de void) que designa potencialmente un objeto; 64) si un lvalue no designa un objeto cuando se evalúa, el comportamiento no está definido. Cuando se dice que un objeto tiene un tipo particular, el tipo se especifica mediante el valor l usado para designar el objeto. Un lvalue modificable es un lvalue que no tiene tipo de matriz, no tiene un tipo incompleto, no tiene un tipo const, y si es una estructura o unión, no tiene ningún miembro (incluido, recursivamente, cualquier miembro o elemento de todos los agregados o uniones contenidos) con un tipo de const-calificado.

Además, un nombre de matriz se convierte en un puntero que apunta al elemento inicial del objeto de la matriz, excepto cuando es el operando del operador sizeof, el operador _Alignof o el operador unario.

De C Estándares # 6.3.2.1p3 :

Excepto cuando es el operando del operador sizeof, el operador _Alignof, o el operador unario, o es un literal de cadena usado para inicializar una matriz, una expresión que tiene tipo '''' matriz de tipo '''' se convierte a una expresión con escriba '''' puntero al tipo '''' que apunta al elemento inicial del objeto de la matriz y no es un valor l.

Dado que str ya está inicializado y cuando asigna algún otro literal de cadena a i th matriz de str , el literal de cadena se convierte en un puntero que hace que la asignación sea incompatible porque tiene lvalue de tipo char array y rvalue de tipo char * . De ahí que el compilador lo informe como un error.

Parte II.III
>> whereas str[i][j]=''J''; is valid.

Sí, esto es válido siempre que i y j sean valores válidos para una matriz dada de matriz.

str[i][j] es de tipo char , por lo que puede asignarle un carácter. Tenga cuidado, C no verifica los límites de la matriz y acceder a una matriz fuera de límites es un comportamiento indefinido que incluye - puede hacer fortuitamente lo que el programador pretendió o falla de segmentación o generar silenciosamente resultados incorrectos o cualquier cosa puede suceder.

Suponiendo que en el Caso 1 , desee crear una matriz de punteros a cadena.
Debería ser así:

char *str[]={"what","is","this"}; ^^

La vista en memoria de str será algo como esto:

str +----+ +-+-+-+-+--+ str[0]| |--->|w|h|a|t|/0| | | +-+-+-+-+--+ +----+ +-+-+--+ str[1]| |--->|i|s|/0| | | +-+-+--+ +----+ +-+-+-+-+--+ str[2]| |--->|t|h|i|s|/0| | | +-+-+-+-+--+ +----+

"what" , "is" y "this" son literales de cadena.
str[0] , str[1] y str[2] son punteros al literal de cadena respectivo y puede hacer que apunten también a otra cadena.

Entonces, esto está perfectamente bien:

str[i]="newstring";

Suponiendo que i sea ​​1, entonces el puntero str[1] ahora apunta a la cadena literal "newstring" cadena de "newstring" :

+----+ +-+-+-+-+-+-+-+-+-+--+ str[1]| |--->|n|e|w|s|t|r|i|n|g|/0| | | +-+-+-+-+-+-+-+-+-+--+ +----+

Pero no deberías hacer esto :

str[i][j]=''j'';

(suponiendo que i=1 y j=0 , entonces str[i][j] es el primer carácter de la segunda cadena)

De acuerdo con el estándar que intenta modificar un literal de cadena, resulta en un comportamiento indefinido, ya que puede almacenarse en un almacenamiento de solo lectura o combinarse con otros literales de cadena.

Desde el estándar C # 6.4.5p7 :

No se especifica si estas matrices son distintas siempre que sus elementos tengan los valores adecuados. Si el programa intenta modificar dicha matriz, el comportamiento no está definido.

Adicional:

No hay un tipo de cadena nativa en el lenguaje C. En lenguaje C, una cadena es una matriz de caracteres terminada en nulo . Debe saber la diferencia entre matrices y punteros.

Le sugiero que lea a continuación para una mejor comprensión sobre matrices, punteros, inicialización de matrices:

  1. Array Inicialización, revisa this .
  2. Equivalencia de punteros y matrices, verifique this y this .

Caso 1: cuando escribo

char*str={"what","is","this"};

luego str[i]="newstring"; es válido mientras que str[i][j]=''j''; es inválido.

Caso 2: cuando escribo

char str[][5]={"what","is","this"};

luego str[i]="newstring"; no es válido, mientras que str[i][j]=''J''; es válida.

¿Por que es esto entonces? Soy un principiante que ya se confunde mucho después de leer las otras respuestas.


Con la primera, define una variable que es un puntero a una char , que generalmente se usa como una sola cadena . Inicializa el puntero para señalar el literal de cadena "what" . El compilador también debería quejarse de que tiene demasiados inicializadores en la lista.

La segunda definición hace str una matriz de tres matrices de cinco caracteres. Es decir, es una matriz de tres cadenas de cinco caracteres.

Un poco diferente se puede ver algo como esto:

Para el primer caso:

+-----+ +--------+ | str | --> | "what" | +-----+ +--------+

Y por el segundo que tienes

+--------+--------+--------+ | "what" | "is" | "this" | +--------+--------+--------+

También tenga en cuenta que para la primera versión, con el puntero a una sola cadena, la expresión str[i] = "newstring" también debería conducir a advertencias, cuando intente asignar un puntero al único elemento char str[i] .

Esa asignación tampoco es válida en la segunda versión, pero por otra razón: str[i] es una matriz (de cinco elementos char ) y no se puede asignar a una matriz, solo se puede copiar. Entonces podrías intentar hacer strcpy(str[i], "newstring") y el compilador no se quejará. Sin embargo, está mal , porque intenta copiar 10 caracteres (recuerde el terminador) en una matriz de 5 caracteres, y eso se escribirá fuera de los límites que conducen a un comportamiento indefinido .


El diseño de la memoria es diferente:

char* str[] = {"what", "is", "this"}; str +--------+ +-----+ | pointer| ---> |what0| +--------+ +-----+ +---+ | pointer| -------------> |is0| +--------+ +---+ +-----+ | pointer| ----------------------> |this0| +--------+ +-----+

En este diseño de memoria, str es una matriz de punteros a las cadenas individuales. Por lo general, estas cadenas individuales residirán en el almacenamiento estático, y es un error intentar modificarlas. En el gráfico, utilicé 0 para denotar los bytes nulos de terminación.

char str[][5] = {"what", "is", "this"}; str +-----+ |what0| +-----+ |is000| +-----+ |this0| +-----+

En este caso, str es una matriz 2D contigua de caracteres ubicados en la pila. Las cadenas se copian en esta área de memoria cuando se inicializa la matriz, y las cadenas individuales se rellenan con cero bytes para dar a la matriz una forma regular.

Estos dos diseños de memoria son fundamentalmente incompatibles entre sí. No puede pasar a una función que espera un puntero al otro. Sin embargo, el acceso a las cadenas individuales es compatible. Cuando escribe str[1] , obtiene un char* para el primer carácter de una región de memoria que contiene los bytes is0 , es decir, una cadena C.

En el primer caso, está claro que este puntero simplemente se carga desde la memoria. En el segundo caso, el puntero se crea a través de array-pointer-decay: str[1] realidad denota una matriz de exactamente cinco bytes ( is000 ), que inmediatamente se descompone en un puntero a su primer elemento en casi todos los contextos. Sin embargo, creo que una explicación completa del array-puntero-decaimiento está más allá del alcance de esta respuesta. Google array-pointer-decay si tienes curiosidad.


Para eliminar la confusión, debe tener una comprensión adecuada de los punteros, matrices e inicializadores. Un error común entre los principiantes de la programación en C es que una matriz es equivalente a un puntero.

Una matriz es una colección de elementos del mismo tipo. considere la siguiente declaración:

char arr[10];

Esta matriz contiene 10 elementos, cada uno de tipo char .

Se puede usar una lista de inicializadores para inicializar una matriz de una manera conveniente. Lo siguiente inicializa los elementos de la matriz con los valores correspondientes de la lista de inicializadores:

char array[10] = {''a'',''b'',''c'',''d'',''e'',''f'',''g'',''h'',''i'',''/0''};

Las matrices no son asignables, por lo que el uso de la lista de inicializadores es válido solo en la declaración de matriz.

char array[10]; array = {''a'',''b'',''c'',''d'',''e'',''f'',''g'',''h'',''i'',''/0''}; // Invalid...

char array1[10]; char array2[10] = {''a'',''b'',''c'',''d'',''e'',''f'',''g'',''h'',''i'',''/0''}; array1 = array2; // Invalid...; You cannot copy array2 to array1 in this manner.

Después de la declaración de una matriz, las asignaciones a los miembros de la matriz deben realizarse a través del operador de indexación de la matriz o su equivalente.

char array[10]; array[0] = ''a''; array[1] = ''b''; . . . array[9] = ''i''; array[10] = ''/0'';

Los bucles son una forma común y conveniente de asignar valores a los miembros de la matriz:

char array[10]; int index = 0; for(char val = ''a''; val <= ''i''; val++) { array[index] = val; index++; } array[index] = ''/0'';

char matrices char pueden inicializarse a través de literales de cadena que son matrices char terminadas nulas constantes:

char array[10] = "abcdefghi";

Sin embargo, lo siguiente no es válido:

char array[10]; array = "abcdefghi"; // As mentioned before, arrays are not assignable

Ahora, vayamos a los punteros ... Los punteros son variables que pueden almacenar la dirección de otra variable, generalmente del mismo tipo.

Considere la siguiente declaración:

char *ptr;

Esto declara una variable de tipo char * , un puntero char . Es decir, un puntero que puede apuntar a una variable char .

A diferencia de las matrices, los punteros son asignables. Por lo tanto, lo siguiente es válido:

char var; char *ptr; ptr = &var; // Perfectly Valid...

Como un puntero no es una matriz, se puede asignar un solo valor a un puntero.

char var; char *ptr = &var; // The address of the variable `var` is stored as a value of the pointer `ptr`

Recuerde que a un puntero se le debe asignar un único valor, por lo tanto, lo siguiente no es válido, ya que el número de inicializadores es más de uno:

char *ptr = {''a'',''b'',''c'',''d'',''/0''};

Esta es una violación de restricción, pero su compilador podría simplemente asignar ''a'' a ptr e ignorar el resto. Pero incluso entonces, el compilador te avisará porque los literales de caracteres como ''a'' tienen tipo int por defecto, y es incompatible con el tipo de ptr que es char * .

Si se ha desreferenciado este puntero en el tiempo de ejecución, se producirá un error en el tiempo de ejecución para acceder a la memoria no válida, lo que hará que el programa falle.

En tu ejemplo:

char *str = {"what", "is", "this"};

de nuevo, esta es una violación de restricción, pero su compilador puede asignarle a la cadena what str e ignorar el resto, y simplemente mostrar una advertencia:

warning: excess elements in scalar initializer .

Ahora, aquí es cómo eliminamos la confusión con respecto a los punteros y matrices: en algunos contextos, una matriz puede decaer a un puntero al primer elemento de la matriz. Por lo tanto, lo siguiente es válido:

char arr[10]; char *ptr = arr;

al usar el nombre de la matriz arr en una expresión de asignación como un valor rvalue , la matriz se desintegra a un puntero a su primer elemento, lo que hace que la expresión anterior sea equivalente a:

char *ptr = &arr[0];

Recuerde que arr[0] es de tipo char , y &arr[0] es su dirección que es de tipo char * , que es compatible con la variable ptr .

Recuerde que los literales de cadena son matrices char terminados nulos, por lo que la siguiente expresión también es válida:

char *ptr = "abcdefghi"; // the array "abcdefghi" decays to a pointer to the first element ''a''

Ahora, en tu caso, char str[][5] = {"what","is","this"}; es una matriz de 3 matrices, cada una contiene 5 elementos.

Como las matrices no son asignables, str[i] = "newstring"; no es válido ya que str[i] es una matriz, pero str[i][j] = ''j''; es válido ya que str[i][j] es un elemento de matriz que NO es una matriz por sí mismo, y es asignable.


Solo porque dijiste que otras respuestas me confundían, veamos qué está pasando con un ejemplo más simple primero

char *ptr = "somestring";

Aquí "somestring" es un literal de cadena que se almacena en la sección de datos de solo lectura de la memoria. ptr es un puntero (asignado como otras variables en la misma sección de código) que apunta al primer byte de esa memoria asignada.

Por lo tanto, cnosider estas dos declaraciones

char *ptr2 = ptr; //statement 1 OK ptr[1] = ''a''; //statement 2 error

La instrucción 1 está haciendo una operación perfectamente válida (asignando 1 apuntador a otra), pero la declaración 2 no es una operación válida (tratando de escribir en una ubicación de solo lectura).

Por otro lado, si escribimos:

char ptr[] = "somestring";

Aquí ptr no es realmente un puntero, sino el nombre de una matriz (a diferencia del puntero, no ocupa más espacio en la memoria). "somestring" la misma cantidad de bytes que requiere "somestring" (no de solo lectura) y eso es todo.

Por lo tanto, considere las mismas dos declaraciones y una declaración adicional

char *ptr2 = ptr; //statement 1 OK ptr[1] = ''a''; //statement 2 OK ptr = "someotherstring" //statement 3 error

La instrucción 1 está haciendo una operación perfectamente válida (asignando el nombre de la matriz a un puntero, el nombre de la matriz devuelve la dirección del primer byte), la declaración 2 también es válida porque la memoria no es de solo lectura.

La instrucción 3 no es una operación válida porque aquí ptr no es un puntero, no puede señalar a otra ubicación de memoria.

Ahora en este código,

char **str={"what","is","this"};

*str es un puntero ( str[i] es lo mismo que *(str+i) )

pero en este código

char str[][] = {"what", "is", "this"};

str[i] no es un puntero. Es el nombre de una matriz.

Lo mismo que arriba sigue.


Antes que nada : una sugerencia: ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡

Dicho esto, para iluminar este escenario particular,

  • En el primer caso ,

    char*str={"what","is","this"};

    no hace lo que crees que hace Es una violación de restricción, que requiere un diagnóstico de cualquier implementación C conforme, según el capítulo§7.7.9 / P2:

    Ningún inicializador intentará proporcionar un valor para un objeto no contenido dentro de la entidad que se está inicializando.

    Si habilitas las advertencias, verías ( al menos )

    advertencia: exceso de elementos en el inicializador escalar

    char*str={"what","is","this"};

    Sin embargo, un compilador (ny) con una estricta conformidad activada debería rechazar la compilación del código. En el caso, el compilador optó por compilar y producir un binario de todos modos, el comportamiento no está dentro del alcance de la definición de lenguaje C, depende de la implementación del compilador (y por lo tanto, puede variar ampliamente).

    En este caso, el compilador decidió esta declaración para hacer funcionalmente solo lo mismo que char*str= "what";

    Entonces, aquí str es un puntero a un char , que apunta a un literal de cadena . Puede reasignar al puntero,

    str="newstring"; //this is valid

    pero, una declaración como

    str[i]="newstring";

    sería inválido , ya que aquí, un tipo de puntero se intenta convertir y almacenar en un tipo de caracteres, donde los tipos no son compatibles. El compilador debería lanzar una advertencia sobre la conversión inválida en este caso.

    A partir de entonces, una declaración como

    str[i][j]=''J''; // compiler error

    es sintácticamente inválido, ya que está utilizando el operador Array subscripting [] en algo que no es "puntero para completar el tipo de objeto", como

    str[i][j] = ... ^^^------------------- cannot use this ^^^^^^ --------------------- str[i] is of type ''char'', not a pointer to be used as the operand for [] operator.

  • Por otro lado, en el segundo caso ,

    str es una matriz de matrices. Puede cambiar elementos de matriz individuales

    str[i][j]=''J''; // change individual element, good to go.

    pero no puedes asignar a una matriz.

    str[i]="newstring"; // nopes, array type is not an lvalue!!

  • Finalmente, teniendo en cuenta que quisiste escribir (como se ve en los comentarios)

    char* str[ ] ={"what","is","this"};

    en su primer caso, se mantiene la misma lógica para las matrices. Esto hace str una serie de punteros. Entonces, los miembros de la matriz son asignables, entonces,

    str[i]="newstring"; // just overwrites the previous pointer

    está perfectamente bien. Sin embargo, los punteros, que se almacenan como miembros de la matriz, son punteros a la cadena literal , por lo que por la misma razón mencionada anteriormente, invoca un comportamiento indefinido , cuando desea modificar uno de los elementos de la memoria que pertenece a la cadena literal

    str[i][j]=''j''; //still invalid, as above.


caso 1 :

char*str={"what","is","this"};

En primer lugar, la declaración anterior no es válida , lea las advertencias correctamente. str es un solo puntero, puede apuntar a una single matriz de caracteres a la vez, no a multiple matriz multiple .

bounty.c: 3: 2: advertencia: exceso de elementos en el inicializador escalar [habilitado por defecto]

str es un char pointer y está almacenado en la section sección de la RAM, pero su contents está almacenado en code(Can''t modify the content sección de code(Can''t modify the content de la RAM porque str se inicializa con una string(in GCC/linux) .

como dijiste str [i] = "newstring"; es válido mientras que str [i] [j] = ''j''; es inválido.

str= "new string" no está causando la modificación del código / sección de solo lectura , aquí simplemente estás asignando una new address a str , por eso es válido pero

*str=''j'' o str[0][0]=''j'' no es válido porque aquí está modificando la sección de solo lectura , tratando de cambiar la primera letra de str .

Caso 2

char str[][5]={"what","is","this"};

aquí str es una matriz 2D es decir, str y str[0],str[1],str[2] se almacenan en la stack section de stack section de la RAM que significa que puedes cambiar cada contenido de str[i] .

str[i][j]=''w''; es válido porque está intentando apilar los contenidos de la sección que es posible. pero

str[i]= "new string"; no es posible porque str[0] sí una matriz y matriz es const pointer (no puede cambiar la dirección) , no puede asignar nueva dirección.

Simplemente en el primer caso str="new string" es valid porque str es pointer , no una array y en el segundo caso str[0]="new string" not valid es not valid porque str es una array no un pointer .

Espero que ayude.


  • En la primera declaración

    char *str={"what","is","this"};

    declara str un puntero a un char y es un escalar. El estándar dice que

    6.7.9 Inicialización (p11):

    El inicializador para un escalar debe ser una sola expresión, opcionalmente encerrado entre llaves . [...]

    Dicho esto, un tipo escalar puede haber preparado un inicializador incluido pero con una sola expresión, pero en el caso de

    char *str = {"what","is","this"}; // three expressions in brace enclosed initializer

    a los compiladores les corresponde cómo va a manejar esto. Tenga en cuenta que lo que sucede con el resto de los inicializadores es un bug . Un compilador de confirmación debería dar un mensaje de diagnóstico.

    [Warning] excess elements in scalar initializer

    5.1.1.3 Diagnóstico (P1):

    Una implementación conforme producirá al menos un mensaje de diagnóstico (identificado de una manera definida por la implementación) si una unidad de traducción de preprocesamiento o unidad de traducción contiene una violación de cualquier regla o restricción de sintaxis, incluso si el comportamiento también se especifica explícitamente como no definido o implementado. definido

  • Usted reclama " str[i]="newstring"; es válido, mientras que str[i][j]=''j''; no es válido. "

    str[i] es de tipo char y solo puede contener un tipo de datos char . La asignación de "newstring" (que es de char * ) no es válida. La declaración str[i][j]=''j''; no es válido ya que el operador de subíndice solo se puede aplicar a una matriz o tipo de datos de puntero.

  • Puedes hacer que str[i]="newstring"; trabajando declarando str como una matriz de char *

    char *str[] = {"what","is","this"};

    En este caso, str[i] es de tipo char * y se le puede asignar un literal de cadena pero la modificación de la cadena literal str[i] apunta a un comportamiento indefinido. Dicho esto, no se puede hacer str[0][0] = ''W'' .

  • El fragmento

    char str[][5]={"what","is","this"};

    declara str como una matriz de matrices de char s. str[i] es en realidad una matriz y como las matrices son valores no modificables, por lo que no puede usarlos como operando izquierdo del operador de asignación. Esto hace que str[i]="newstring"; inválido. Mientras str[i][j]=''J''; funciona porque los elementos de una matriz se pueden modificar.


  • Para empezar

    char*str={"what","is","this"};

    ni siquiera es un código C válido 1) , por lo que discutirlo no es muy significativo . Por algún motivo, el compilador gcc deja pasar este código solo con una advertencia. No ignore las advertencias del compilador. Al usar gcc, asegúrese de compilar siempre usando -std=c11 -pedantic-errors -Wall -Wextra .

  • Lo que parece hacer gcc al encontrar este código no estándar, es tratarlo como si hubiera escrito char*str={"what"}; . Que a su vez es lo mismo que char*str="what"; . Esto de ningún modo está garantizado por el lenguaje C.

  • str[i][j] intenta indirectar un puntero dos veces, a pesar de que solo tiene un nivel de direccionamiento indirecto y, por lo tanto, obtienes un error de compilación. Tiene tan poco sentido como escribir

    int array [3] = {1,2,3}; int x = array[0][0]; .

  • En cuanto a la diferencia entre char* str = ... y char str[] = ... , vea Preguntas frecuentes: ¿Cuál es la diferencia entre char s [] y char * s? .

  • Con respecto al char str[][5]={"what","is","this"}; caso, crea una matriz de matrices (matriz 2D). La dimensión más interna se establece en 5 y el compilador configura automáticamente la dimensión más externa en función de cuántos inicializadores proporcionó el programador. En este caso 3, entonces el código es equivalente a char[3][5] .

  • str[i] te da el número de matriz i en la matriz de matrices. No se puede asignar a matrices en C, porque así es como se diseña el lenguaje. Además, sería incorrecto hacerlo para una cadena de todos modos, Preguntas frecuentes: ¿Cómo asignar correctamente un nuevo valor de cadena?

1) Esta es una violación de restricción de C11 6.7.9 / 2. Ver también 6.7.9 / 11.