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

6 minutos de lectura

avatar de usuario
Ravi Gupta

¿No es posible usar memset en una matriz de enteros? Intenté lo siguiente memset llamada y no obtuvo los valores enteros correctos en el int formación.

int arr[5];
memset (arr, -1, sizeof(arr)/sizeof(int));

Los valores que obtuve son:

arr[0] = -1
arr[1] = 255
arr[2] = 0
arr[3] = 0
arr[4] = 0

  • podría ser más fácil hacer esto: int arr[5] = {-1};

    – Thomas Dignan

    26 de agosto de 2011 a las 9:17

  • @Tom Dignan: excepto que solo inicializa el primer elemento en -1 y todo el resto en 0.

    – hombre de hojalata

    26 de agosto de 2011 a las 9:46

avatar de usuario
Ioan Paul Pirau

solo cambia a memset (arr, -1, sizeof(arr));

Tenga en cuenta que para otros valores que no sean 0 y -1 esto no funcionaría ya que conjunto de miembros establece los valores de byte para el bloque de memoria que comienza en la variable indicada por *ptr para el siguiente num bytes

void * memset ( void * ptr, int value, size_t num );

Y desde int está representado en más de un byte, no obtendrá el valor deseado para los enteros en su matriz.

Excepciones:

  • 0 es una excepción ya que, si establece todos los bytes en 0, el valor será cero
  • -1 es otra excepción ya que, como destacó Patrick, -1 es 0xff (=255) en int8_t y 0xffffffff en int32_t

La razón por la que tienes:

arr[0] = -1
arr[1] = 255
arr[2] = 0
arr[3] = 0
arr[4] = 0

Es porque, en su caso, la longitud de un int es de 4 bytes (representación de 32 bits), la longitud de su matriz en bytes es de 20 (= 5 * 4), y solo establece 5 bytes en -1 (= 255) en lugar de 20.

  • Bueno, en este caso particular (para -1 como valor) memset realmente funciona. Porque -1 es 0xff en int8_t y 0xffffffff en int32_t y así sucesivamente. IOW: memset funciona bien para 0 y -1 pero no es muy útil para todos los demás casos.

    – Patricio B.

    26 de agosto de 2011 a las 9:16

  • Tienes razón Patrick, gracias. Cambié mi respuesta en consecuencia.

    – Ioan Paul Pirau

    26 de agosto de 2011 a las 9:22

  • @Patrick B.: funcionará bien en muchas plataformas, pero no en todas. No todas las plataformas usan el complemento a dos, y también puede desencadenar representaciones de trampas usando memset para inicializar un int.

    – Sander de Dycker

    26 de agosto de 2011 a las 9:44

  • cada int cuyos cuatro bytes tengan el mismo valor puede usar memset, no solo 0 y -1

    – phuclv

    27 de diciembre de 2013 a las 1:31

  • @LưuVĩnhPhúc, pero ¿están garantizadas las representaciones además de 0? stackoverflow.com/q/11138188/895245 dice que sí para 0, pero creo que no para otros porque no sabemos dónde están los bits de relleno y de signo dentro de cada int.

    – Ciro Santilli Путлер Капут 六四事

    10 mayo 2016 a las 18:35

avatar de usuario
Sander De Dycker

no usar memset para inicializar cualquier cosa que no sean tipos de datos de un solo byte.

A primera vista, podría parecer que debería funcionar para inicializar un int para 0 o -1 (y en muchos sistemas funcionará), pero entonces no está teniendo en cuenta la posibilidad de que pueda generar una representación de trampa, causando un comportamiento indefinido, o el hecho de que la representación de enteros no es necesariamente complemento de dos.

La forma correcta de inicializar una matriz de int para -1es recorrer la matriz y establecer cada valor explícitamente.

  • Creo que esta respuesta debe ser ponderada por una cláusula como “No use memset()si quieres escribir código absolutamente portátil“. La mayoría de la gente ni escribe ni tiene la intención de escribir código portátil. La mayoría de la gente llama al código “portátil” cuando funciona para dos arquitecturas. La palabra “correcto” en “La forma correcta…” también podría cambiarse a “portátil”. Si no está tratando de escribir un código absolutamente portátil, no es ni más ni menos correcto.

    – Pascal Cuoq

    26 de agosto de 2011 a las 16:38


  • +1 @Complicatedseebio no podría estar más de acuerdo, demasiados programadores saltan a la garganta de las personas con cosas como ‘correcto’ y ‘stl esto’. Con demasiada frecuencia pasan por alto lo que necesita el problema específico.

    – Adam Naylor

    15 de febrero de 2012 a las 21:22

  • @Complicated ver bio @Adam: Sin embargo, la cuestión es que inicializar una matriz de int Se garantiza que el uso de un bucle funcionará en todos los casos, mientras que el uso de memset podría no hacerlo correctamente (o peor aún podría aparecer trabajar). No diré que no puedes usar memset si tiene un conocimiento íntimo de las plataformas en las que se ejecutará el código y sabe que no causará ningún problema. Pero no tengo tanto conocimiento sobre las plataformas de todos los que puedan leer esta respuesta, así que prefiero ir a lo seguro. Espero que equilibre algunos de los “extremos” (por el bien del argumento) que usé en mi respuesta.

    – Sander de Dycker

    16 de febrero de 2012 a las 8:23

  • Voto a favor de Sander, no entendí por qué el -1 no funcionaba para mí hasta que me di cuenta de que la máquina con la que estaba trabajando no era 2-complement.

    – capitán666

    16 de noviembre de 2013 a las 14:08

  • @ capitano666 – solo curiosidad – ¿qué procesador (“máquina”) estabas usando?

    – Federico

    9 de noviembre de 2016 a las 22:59

avatar de usuario
Faiz Halde

gcc proporciona un buen atajo de inicialización de matriz

int arr[32] = {[0 ... 10] = 3, [11 ... 31] = 4}

cuidado con el espacio antes y después ...

¿Por qué la división?

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

Tu versión, sizeof(arr)/sizeof(int)le da el número de elementos en la matriz.

Puede ahorrarse algo de escritura inicializando la matriz directamente:

int arr[5] = {-1, -1, -1, -1, -1}; 

Esa línea es más corta que el memset, y también funciona.

  • +1 para inicializador de matriz, aunque es útil solo para algunos valores.

    – Martín Konicek

    21 de octubre de 2012 a las 17:12

  • También se podría abreviar eso y omitir la especificación explícita de la cantidad de elementos, ya que el compilador detecta la cantidad de elementos por la cantidad de inicializaciones: int arr[] = {-1, -1, -1, -1, -1}; .

    – RobertS apoya a Mónica Cellio

    8 de marzo de 2020 a las 11:13

avatar de usuario
RobertS apoya a Mónica Cellio

void * memset ( void * ptr, int value, size_t num );

Esta función funciona bien en la mayoría de los sistemas cuando se aplica para establecer una matriz de caracteres. Establece el primer número de BYTES del bloque de memoria señalado por ptr en el valor especificado (interpretado como un carácter sin signo). Referencia de memset-C++
Opera un byte cada vez. Así que funciona bien si asignas los segundos argumentos con un valor int no mayor a 0xff.

En cuanto a su versión, el tercer argumento es la cantidad de elementos de la matriz, por lo que obtuvo su resultado. En realidad, la verdad es que se supone que debes asignar a los terceros argumentos el NÚMERO DE BYTES que deseas.

Así que la versión correcta debería ser así:

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

  • +1 para inicializador de matriz, aunque es útil solo para algunos valores.

    – Martín Konicek

    21 de octubre de 2012 a las 17:12

  • También se podría abreviar eso y omitir la especificación explícita de la cantidad de elementos, ya que el compilador detecta la cantidad de elementos por la cantidad de inicializaciones: int arr[] = {-1, -1, -1, -1, -1}; .

    – RobertS apoya a Mónica Cellio

    8 de marzo de 2020 a las 11:13

¿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