No entender lo que hace la expresión *(uint32_t*)

5 minutos de lectura

Avatar de usuario de Hoa.N
hoa.n

no entiendo cual es la expresion *(uint32_t*) lo hace.

He desglosado la declaración en un ejemplo que declara las partes para que pueda intentar interpretar lo que hace cada una.

  uint32_t* ptr;
  uint32_t num
  *(uint32_t*)(ptr + num); // <-- what does this do?

No entiendo la última parte del ejemplo, qué sucede cuando la expresión *(uint32_t*)(ptr + num); se ejecuta durante el tiempo de ejecución?

  • Este elenco es inútil aquí. En realidad, toda la expresión es. ptr + num es uint32_t * de todos modos.

    – Eugenio Sh.

    16 de febrero de 2018 a las 19:58


  • Nótese que esta definición apareció por primera vez en C99.

    – mpontillo

    9 de abril de 2019 a las 5:18

  • Tengo que decir, dadas las definiciones aquí, *(uint32_t*)(ptr + num) de hecho es lo mismo que *(ptr + num)que es por supuesto ptr[num]. Esta última forma es preferible en mi humilde opinión

    – bobbogo

    23 de abril de 2019 a las 14:36


  • Lo hace qué?

    -Peter Mortensen

    26 de abril de 2021 a las 12:48

Avatar de usuario de Pablo
Pablo

uint32_t es un tipo numérico que garantiza 32 bits. El valor no tiene signo, lo que significa que el rango de valores va de 0 a 232 – 1.

Este

uint32_t* ptr;

declara un puntero de tipo uint32_t*, pero el puntero no está inicializado, es decir, el puntero no apunta a ningún lugar en particular. Intentar acceder a la memoria a través de ese puntero provocará un comportamiento indefinido y su programa podría bloquearse.

Este

uint32_t num;

es solo una variable de tipo uint32_t.

Este

*(uint32_t*)(ptr + num);

ptr + num le devuelve un nuevo puntero. Se llama aritmética de punteros. Es como la aritmética normal, solo que el compilador tiene en cuenta el tamaño de los tipos. Pensar en ptr + num como la dirección de memoria basada en el original ptr puntero más el número de bytes para num uint32_t objetos.

los (uint32_t*) x es un elenco Esto le dice al compilador que debe tratar la expresión x como si fuera un uint32_t*. En este caso, ni siquiera es necesario, porque ptr + num ya es un uint32_t*.

los * al principio está el operador de desreferenciación que se utiliza para acceder a la memoria a través de un puntero. Toda la expresión es equivalente a

ptr[num];

Ahora, debido a que ninguna de estas variables está inicializada, el resultado será basura.

Sin embargo, si los inicializas así:

uint32_t arr[] = { 1, 3, 5, 7, 9 };
uint32_t *ptr = arr;
uint32_t num = 2;

printf("%u\n", *(ptr + num));

esto imprimiría 5, porque ptr[2] es 5

  • OK excepto por el especificador printf. "%" PRIu32 es mejor. "%u" partidos unsigned.

    – chux – Reincorporar a Monica

    16 de febrero de 2018 a las 20:09


  • @chux huy, el gremlin del teclado me atacó, tantos “errores tipográficos”. arreglé el printf especificador, no había pensado en eso.

    – pablo

    16 de febrero de 2018 a las 20:11

  • entonces cual es la diferencia entre uint32_t y int32_t

    – Travis Su

    2 de febrero de 2020 a las 0:30

  • @TravisSu leyó la primera oración de mi respuesta. uint32_t es para enteros de 32 bits sin signo, lo que significa que almacena valores entre 0 y 4294967295 y int32_t es para enteros de 32 bits con signo, lo que significa que almacena valores entre -2147483648 y 2147483647.

    – pablo

    2 de febrero de 2020 a las 3:13

  • Python de autoaprendizaje y esto es muy claro gracias

    – n00dles

    16 de noviembre de 2021 a las 4:41

avatar de usuario de user7610
usuario7610

uint32_t se define en stdint.hpor lo que es posible que sea necesario incluirlo

#include <stdint.h>

este encabezado definirá uint32_t ser un tipo entero sin signo que toma exactamente 32 bits.

  • Este comentario no responde a la pregunta “¿Qué es *(uint32_t*)?”

    – Lundin

    4 de junio de 2020 a las 11:47

  • Más bien agregando esto como un comentario.

    – Haseeb Mir

    25 de septiembre de 2021 a las 15:19

avatar de usuario de giusti
giusti

Esto realmente no hace nada. Déjame darte un ejemplo diferente:

uint32_t data;
void *pointer = &data;
*(uint32_t *)pointer = 5;

Ante todo, void* significa puntero “genérico”. Puede apuntar a objetos de cualquier tipo.

Ahora, (uint32_t *) significa “interpretar pointer como un puntero a un objeto con tipo uint32_t.

El resto de la expresión simplemente significa “almacenar 5 en la ubicación almacenada por este puntero”.

Si quieres saber qué uint32_t es, que es un entero sin signo con exactamente 32 bits. Y pointer + num es la misma que la dirección de pointer[5].

  • void *pointer = &data; es C++ válido. ¿Es la conversión implícita de void * a otros tipos de punteros que no son válidos en C++.

    – Santo Gato Negro

    16 de febrero de 2018 a las 20:14


Este tipo de expresión se suele utilizar en los juegos de palabras. Si no está familiarizado con los juegos de palabras, la idea principal es omitir el sistema de tipos para que pueda tratar algo como un tipo diferente de lo que realmente es (es decir, tratar un int a como doble)

La idea principal detrás del juego de palabras es tomar un puntero a una variable actual y luego convertirlo en un tipo diferente convirtiéndolo en un puntero de ese tipo y luego desreferenciarlo, de ahí el uso común de conversión y desreferencia a la que se refiere ( *(uint32_t *) = convertir a un puntero int de 32 bits sin firmar y luego eliminar la referencia).

Como han señalado otros, su código “no hace nada” porque está cambiando un int a un int, lo que no tiene ningún efecto. Sin embargo, si quisieras convertir un int en un doble…

uint32_t num=5;
double& myvar=*(double*) &num;

Ahora puedes manipular nums memoria como una doble vía myvar a pesar de num sigue siendo un Int. Esta es una idea terrible y solo pretende ser un ejemplo de juguete del uso de juegos de palabras.

¿Ha sido útil esta solución?