Usando memset para una matriz de enteros en C

6 minutos de lectura

avatar de usuario
usuario1762571

char str[] = "beautiful earth";
memset(str, '*', 6);
printf("%s", str);

Output:
******ful earth

Al igual que el uso anterior de memset, ¿podemos inicializar solo unos pocos valores de índice de matriz de enteros a 1 como se indica a continuación?

int arr[15];
memset(arr, 1, 6);

  • posible duplicado de la matriz de enteros de memset?

    -Joe Frambach

    25 de junio de 2013 a las 3:52

  • No. memset() reduce a un byte y lo engaña en toda la región.

    – Místico

    25 de junio de 2013 a las 3:53

  • Siempre puede leer la documentación de memset para averiguar qué hace.

    –Jim Balter

    25 de junio de 2013 a las 5:51

  • @JoeFrambach La respuesta aceptada a esa pregunta no se aplica aquí.

    –Jim Balter

    25 de junio de 2013 a las 5:53

  • Posible duplicado de ¿Por qué “memset (arr, -1, sizeof (arr)/sizeof (int))” no borra una matriz de enteros a -1?

    – Andrik007

    13 oct 2019 a las 17:50

avatar de usuario
jonathan reinhart

No, no puedes usar memset() Me gusta esto. los página de manual dice (énfasis mío):

los memset() la función llena la primera n bytes del área de memoria señalada por s con el byte constante c.

Desde un int suele ser de 4 bytes, esto no es suficiente.


Si usted (¡¡incorrectamente!!) intenta hacer esto:

int arr[15];
memset(arr, 1, 6*sizeof(int));    //wrong!

entonces los primeros 6 ints en la matriz en realidad se establecerá en 0x01010101 = 16843009.

La única vez que es realmente aceptable escribir sobre una “mancha” de datos con tipos de datos que no son bytes, es memset(thing, 0, sizeof(thing)); para “poner a cero” toda la estructura/matriz. Esto funciona porque NULL, 0x00000000, 0.0, son completamente ceros.


La solución es usar un for Bucle y configúrelo usted mismo:

int arr[15];
int i;

for (i=0; i<6; ++i)    // Set the first 6 elements in the array
    arr[i] = 1;        // to the value 1.

  • Estaría más convencido por su afirmación de que memset hizo esto si comienza inicializando toda la matriz a 0 (usando int arr[15] = {0}) y luego haciendo el memset(arr, 1, 8); Y si todavía tiene una matriz llena de 0x01010101 después de eso, tiene un tiempo de ejecución c con errores :-).

    –Mike Woolf

    25 de junio de 2013 a las 4:06


  • @MikeWoolf Cierto. Mi comentario fue dirigido al OP. Ciertamente es libre de codificar lo que quiera, pero si espera de alguna manera truco memset para inicializar su matriz, va a terminar mal.

    – Jonathan Reinhart

    25 de junio de 2013 a las 4:31

  • @briankip La matriz se descompone en un puntero aquí. los & es opcional en este caso; memset(&arr, ...) haría lo mismo.

    – Jonathan Reinhart

    20 de marzo de 2016 a las 15:57


  • @JonathonReinhart Redacción peligrosa (‘& es opcional’). Ambas variantes funcionan, ya que memset acepta void*pero el tipo de puntero es diferente: arr decae a int* mientras que &arr da un puntero de tipo int(*)[15]!

    – Aconcagua

    23 de octubre de 2018 a las 13:03


  • @Jacqueline P. Si cree que esta respuesta es incorrecta, lo correcto es dejar un comentario, no sugerir una edición. De esa manera puedo explicar por qué su comprensión no es del todo correcta.

    – Jonathan Reinhart

    11 de marzo de 2020 a las 5:26


Respuesta corta, NO.

Respuesta larga, memset establece bytes y funciona para caracteres porque son bytes individuales, pero los números enteros no lo son.

En Linux, OSX y otros sistemas operativos similares a UNIX donde wchar_t es de 32 bits y puedes usar wmemset() en lugar de memset().

#include<wchar.h>
...
int arr[15];
wmemset( arr, 1, 6 );

Tenga en cuenta que wchar_t en MS-Windows es de 16 bits, por lo que es posible que este truco no funcione.

  • ¿Por qué usarías este truco no portátil en lugar de un bucle simple?

    – Ayxan Haqverdili

    24 de enero de 2021 a las 16:24

El tercer argumento de memset es el tamaño de byte. Por lo tanto, debe establecer el tamaño total de bytes de arr[15]

memset(arr, 1, sizeof(arr));

Sin embargo, es probable que desee establecer el valor 1 para elementos completos en arr. Entonces es mejor que te pongas en el bucle.

for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
    arr[i] = 1;
}

Porque memset() establezca 1 en cada byte. Así que no es lo que esperabas.

Como nadie lo mencionó…

Aunque no puede inicializar los enteros con valor 1 usando memset, usted lata inicializarlos con valor -1 y simplemente cambie su lógica para trabajar con valores negativos en su lugar.

Por ejemplo, para inicializar los primeros 6 números de su matriz con -1tu harías

memset(arr,-1,6*(sizeof int));

Además, si solo necesita hacer esta inicialización una vez, puede declarar la matriz para comenzar con valores 1 desde el tiempo de compilación.

int arr[15] = {1,1,1,1,1,1};

  • Tienes razón técnicamente, pero si viera eso en una revisión de código, probablemente lo perdería.

    – Jonathan Reinhart

    25 de junio de 2013 a las 4:14

  • Esto solo funcionará en plataformas que usen complemento a 2 para representar números negativos. A pesar de que prácticamente todas las plataformas hoy en día son complemento de 2, esto sigue siendo un truco.

    – Ant

    25 de junio de 2013 a las 4:33

no, no puedes [portably] utilizar memset para ese propósito, a menos que el valor objetivo deseado sea 0. memset trata la región de memoria de destino como una matriz de bytes, no como una matriz de ints.

Un truco bastante popular para llenar una región de memoria con un patrón repetitivo en realidad se basa en memcpy. Se basa críticamente en la expectativa de que memcpy copia los datos en la dirección de avance

int arr[15];

arr[0] = 1;
memcpy(&arr[1], &arr[0], sizeof arr - sizeof *arr);

Este es, por supuesto, un truco bastante feo, ya que el comportamiento de estándar memcpy no está definido cuando las regiones de memoria de origen y destino se superponen. Puedes escribir tu propia versión de memcpy sin embargo, asegurándose de que copie los datos en la dirección de avance y úselo de la manera anterior. Pero realmente no vale la pena. Simplemente use un ciclo simple para establecer los elementos de su matriz en el valor deseado.

  • Tienes razón técnicamente, pero si viera eso en una revisión de código, probablemente lo perdería.

    – Jonathan Reinhart

    25 de junio de 2013 a las 4:14

  • Esto solo funcionará en plataformas que usen complemento a 2 para representar números negativos. A pesar de que prácticamente todas las plataformas hoy en día son complemento de 2, esto sigue siendo un truco.

    – Ant

    25 de junio de 2013 a las 4:33

avatar de usuario
Troya

En realidad es posible con memset_pattern4 que establece 4 bytes a la vez.

memset_pattern4(your_array, your_number, sizeof(your_array));

  • se pone 4 bytes a la vez, no 4 bits

    – phuclv

    31 de julio de 2021 a las 16:44

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad