Teniendo esto:

#include <stdio.h>
#include <stdlib.h>

struct Test { char c; } foo;

int main (void) {

   struct Test **ar;
   ar=malloc(16);
   *(ar+1) = &foo;
   ar[1]->c = 'c'; //this work
  (*(*ar+1)).c = 'c'; //this does't work

   return 0;
}
        //(**(ar+1)).c='c'; --> first case

¿Por qué lo anterior funciona solo con la variante con entrada de matriz y no con desreferencia de puntero?

struct Test { char c; } foo;

int main (void) {

   struct Test **ar;
   ar=malloc(16);
   *ar=malloc(0);
   *(ar+1) = &foo;
   //(**(ar+1)).c='c';
   (*(*ar+1)).c='c'; // NOW IT WORKS --> second case
   printf("%c\n", (*(*ar+1)).c); //prints 'c'

   return 0;
}

Ahora incluso asigna 0 bytes, eso no importa ya que solo quiero una dirección proporcionada por el sistema operativo para tener el primer elemento inicializado

Pregunta: ¿cómo funciona la aritmética del puntero en ambos casos? Según tengo entendido ellos:

1) primero Para llegar al valor de struct Test, el puntero va directamente de la dirección señalada por ar al valor de l por **ar - sizeof(struct Test**)

2) en el segundo caso, el puntero ha inicializado el primer miembro ar[0], por lo que comienza aquí *ar y va al valor l por *ar - sizeof(struct Test*).

Pero ambos punteros tienen el mismo tamaño sizeof(struct Test**) == sizeof(struct Test*) y, por lo tanto, ¿no debería haber diferencia en la aritmética, o me falta algo?

0
Herdsman 8 may. 2020 a las 01:22

3 respuestas

struct Test **ar;
ar=malloc(16);
...
(*(*ar+1)).c = 'c'; //this does't work

Por supuesto que no. Como se señaló en mi comentario, * tiene mayor prioridad que + C Precedencia del operador. Entonces, ¿qué está pasando en (*(*ar+1)).c? Mirar:

(*ar+1)

Que es equivalente a:

ar[0] + 1

Dado que el tipo para ar es un puntero a puntero struct Test, *ar o ar[0] es escriba puntero a struct Test. Luego agrega + 1 que agrega sizeof (struct Test) a ar cuando lo que desea hacer es agregar sizeof (a_pointer) a ar para abordar el siguiente puntero NO la próxima estructura .

2
David C. Rankin 7 may. 2020 a las 22:57

Para empezar, debe especificar correctamente el tamaño de la memoria asignada

   ar = malloc( 2 * sizeof( struct Test * ) );

Esta declaración

*(ar+1) = &foo;

Establece el segundo elemento de la matriz asignada de punteros a la dirección de la variable global foo.

Es lo mismo que

ar[1] = &foo;

Esta expresión

*ar

Eso es equivalente a la expresión

ar[0]

Da el primer elemento de la matriz asignada de punteros. No fue inicializado. Como resultado esta expresión

*ar+1

O

ar[0] + 1

Invoca un comportamiento indefinido (Agregar 1 a algo que no se inicializó y tiene un valor indeterminado).

Parece que quieres decir

(**(ar+1)).c = 'c';

Esa es la expresion

*( ar + 1 )

Da el segundo elemento de la matriz de punteros asignada dinámicamente. Al desreferenciarlo se obtiene la dirección del objeto foo. Anulando la referencia la segunda vez que obtienes el valor del objeto en sí.

Presta atención a que la expresión

ar[1]

Es equivalente a

*( ar + 1 )

Y como puedes ver en esta declaración válida

ar[1]->c = 'c'

La expresión anterior produce un puntero. Por lo tanto, debe desreferenciarlo si desea utilizar el operador.

**( ar + 1 )
1
Vlad from Moscow 7 may. 2020 a las 22:56

Desea desreferenciar para obtener ar[i], hagamos lo siguiente:

(*(ar+1))->c = 'c';
0
Hitokiri 7 may. 2020 a las 22:29