vectores suma que punteros puntero declarar declaracion con como cadenas arreglos aritmetica apuntadores c arrays pointers

suma - ¿Por qué esta aritmética de puntero no está permitida en C?



que es un puntero en c (6)

Hasta donde yo sé, una expresión que tiene un tipo de matriz se convierte en un tipo de puntero que apunta al elemento inicial de la matriz.

Es cierto en la mayoría de los contextos. No es cierto en los siguientes contextos:

  1. Al usar la dirección del operador ( &arr ). El tipo de &arr es char (*)[6] . No es char** .

  2. Cuando se usa el operador sizeof . sizeof(arr) es 6 . Si hubiera sido un puntero, sería del tamaño de un puntero (4 u 8 en las plataformas más comunes).

  3. Cuando se usa como el LHS de un operador de asignación. Una variable del tipo de matriz no es modificable.

Por lo tanto, esperaba que arr = arr + 1 (el puntero al primer elemento (arr) de la matriz se convierta en el puntero al segundo elemento de la matriz) para que funcione. ¿Por qué este trabajo no funciona en C?

El RHS de la expresión se evalúa como un puntero al segundo elemento de arr . Sin embargo, esa línea no funciona debido a (3) arriba. arr no es un valor modificable. No se puede usar como el LHS de un operador de asignación.

Esta pregunta ya tiene una respuesta aquí:

char arr[] = "Hello"; arr = arr + 1; // error occurs

Hasta donde yo sé, una expresión que tiene un tipo de matriz se convierte en un tipo de puntero que apunta al elemento inicial de la matriz. Por lo tanto, esperaba que arr = arr + 1 (el puntero al primer elemento (arr) de la matriz se convierta en el puntero al segundo elemento de la matriz) para que funcione. ¿Por qué esto no funciona en C?


Esto se debe a que las matrices son similares a los punteros, excepto que no se pueden modificar. Sin embargo, puede modificar un puntero que apunta a una matriz. Para el ejemplo anterior puedes hacer esto:

char arr[]="Hello"; char *ptr=arr; ptr=ptr+1;

Inicialmente, el puntero ptr apuntará al primer carácter de la matriz, es decir, ''H'' y, después de modificar el valor, apuntará al segundo carácter, es decir, ''e'' . También puede hacer lo siguiente:

char arr[]="Hello"; char *ptr=arr; ptr=arr+1;

Ambos producen el mismo efecto que muestra que arr+1 es en verdad una aritmética de puntero. Sin embargo, no puede modificar el valor de arr porque su tipo es el de una matriz de caracteres y no un puntero a una matriz de caracteres.


Las matrices son lvalues ​​no modificables. No pueden ser el operando izquierdo de un operador de asignación.

C11-§6.3.2.1:

Un lvalue modificable es un lvalue que no tiene tipo de matriz , no tiene un tipo incompleto, [...]

§6.5.16 / 2:

Un operador de asignación tendrá un valor l modificable como su operando izquierdo.

En la declaración

arr = arr + 1;

arr es el operando izquierdo de = operator y es del tipo array. No puede ser modificado.
Por lo tanto, no es la aritmética del puntero sino la restricción del lenguaje en el operador de asignación la razón del error sintáctico.

Tenga en cuenta que en algunos contextos, las matrices decaen a un puntero a su primer elemento, aunque los punteros y las matrices son tipos diferentes. Las matrices no son punteros . Solo la indexación aritmética y de matriz de puntero son equivalentes. Por ejemplo

char *ptr = &arr[0] + 1 => &(*(arr + 0)) + 1 => &(*arr) + 1 => arr + 1 // * and & nullify each other


Porque arr no es un puntero sino una matriz char. Puede verificar esto marcando sizeof arr . Para obtener un puntero a char, debe usar char *arr = "Hello"; .

La mayor diferencia entre un puntero y una matriz es que puede asignar directamente un valor a un puntero, pero no puede hacerlo a una matriz.

De hecho, cuando escribe arr + 1 , arr "se descompone" en el puntero a su primer elemento, es decir, arr == &arr[0] . Entonces arr + 1 es la aritmética legal del puntero, pero dar su valor a arr , que es una matriz, es ilegal.


arr + 1 es de hecho un puntero al segundo elemento de la matriz (es decir, &arr[1] ).

Sin embargo, eso no significa que pueda escribir de alguna manera el valor del puntero en arr . No puedes hacerlo por al menos dos razones.

En primer lugar, arr es una matriz de elementos char , no un puntero. Hay un desacuerdo de tipo obvio aquí.

En segundo lugar, al ser una matriz, arr no modificable . No puedes cambiar arr , solo puedes cambiar sus elementos (esta distinción es algo difícil de entender, pero está ahí).

Finalmente, si simplemente ignoramos las complejidades más profundas y nos concentramos en lo que sucede formalmente en el nivel superior, debido a la descomposición del tipo de matriz, su expresión es equivalente a

(char *) arr = (char *) arr + 1;

La asignación es imposible ya que el lado izquierdo es el resultado de una conversión de tipo [implícito]. En C, las conversiones de tipo siempre producen valores r. No se puede asignar a rvalues.

En otras palabras, no es la "aritmética del puntero" la que no está permitida aquí. La aritmética del puntero está bien. Es lo que haces con el resultado de esa aritmética de puntero que causa el error.


char[] no es puntero, mientras que char* es un puntero. Esto funciona, pero es una solución incorrecta:

int main() { char *arr = "Hello"; arr = arr + 1; // Wrong! printf("%s/n", arr); // Output: ello }

Si arr se asigna en forma de pila con malloc se puede producir una pérdida de memoria si free memoria free empieza arr+1 arr .

Pero puedes hacer algo como esto:

int main() { char arr[] = "Hello"; char *wordFromSecondLetter = &arr[0] + 1; printf("%s/n", wordFromSecondLetter); // Output: ello }

O así

int main() { char arr[] = "Hello"; printf("%s/n", &arr[1]); // Output: ello }