es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

obteniendo los valores de un puntero void sin conocer más que el tamaño de cada elemento

Comenzaré diciendo que he visto un montón de publicaciones con títulos similares, pero ninguno se centra en mi pregunta.

Me han asignado la tarea de hacer una función que reciba un void* arr, un tamaño sin signo sizeofArray y un tamaño sin signo sizeofElement. Logré iterar a través del arreglo sin problema, sin embargo, cuando intento imprimir los valores o hacer algo con ellos, parecen ser basura a menos que especifique su tipo de antemano.

Esta es mi función:

void MemoryContent(void* arr, unsigned int sizeRe, unsigned int sizeUnit)
{
int sizeArr = sizeRe/sizeUnit;

for (int i = 0; i < sizeArr ; i++)
{
    printf("%d\n",arr); // esto imprime basura
    printf("%d\n",*(int*)arr); // esto imprime los valores esperados dado que el arreglo es de tipo int*
    arr = arr + sizeUnit;
}

}

La salida de esto con el siguiente arreglo (int arr[] = {1, 2, 4, 8, 16, 32, -1}) es:

-13296 1
-13292 2
-13288 4
-13284 8
-13280 16
-13276 32
-13272 -1

Me doy cuenta de que debo especificar de alguna manera el tipo. Aunque el printf en realidad no se utilizará, ya que necesito la representación binaria de cualquier valor que haya ahí (esto ya está resuelto en otra función), aún no estoy seguro de cómo obtener el valor real sin necesidad de una conversión, pero sabiendo el tamaño del elemento. Agradecería mucho cualquier explicación.

Nota: El compilador utilizado es gcc, por lo que las aritméticas de punteros están permitidas.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    En tu función, estás iterando a través del arreglo void utilizando la aritmética de punteros, lo cual está permitido en C. Sin embargo, dado que el puntero es de tipo void, el compilador no puede determinar el tipo de datos al cual está apuntando, de ahí la salida basura al intentar imprimir los valores.

    Para obtener el valor real de los datos en el arreglo void sin necesidad de realizar una conversión explícita, pero teniendo en cuenta el tamaño de los datos, puedes utilizar una declaración switch para determinar el tamaño de los datos y luego convertir el puntero void al tipo de datos correspondiente antes de imprimirlo.

    Aquí te muestro una versión actualizada de tu función que hace esto:

    void MemoryContent(void* arr, unsigned int sizeRe, unsigned int sizeUnit)
    {
        int sizeArr = sizeRe/sizeUnit;
        void* elemPtr;
    
        for (int i = 0; i < sizeArr ; i++)
        {
            elemPtr = arr + (i * sizeUnit); // puntero al elemento actual en el arreglo
    
            switch(sizeUnit) {
                case sizeof(char):
                    printf("%d\n", *(char*)elemPtr);
                    break;
                case sizeof(short):
                    printf("%d\n", *(short*)elemPtr);
                    break;
                case sizeof(int):
                    printf("%d\n", *(int*)elemPtr);
                    break;
                case sizeof(long):
                    printf("%ld\n", *(long*)elemPtr);
                    break;
                case sizeof(float):
                    printf("%f\n", *(float*)elemPtr);
                    break;
                case sizeof(double):
                    printf("%f\n", *(double*)elemPtr);
                    break;
                default:
                    printf("Tipo de dato desconocido\n");
                    break;
            }
        }
    }
    

    Esta función actualizada utiliza una declaración switch para determinar el tamaño de los datos en cada elemento apuntado por el puntero void, convierte el puntero void al tipo de datos correspondiente y luego imprime el valor utilizando el especificador de formato correcto para el tipo de datos.

    Ten en cuenta que esta función asume que los tipos de datos en el arreglo son uno de los tipos básicos de C (char, short, int, long, float, double). Si tus tipos de datos son más complejos (por ejemplo, structs), deberás manejarlos de manera diferente.

Comments are closed.