66 votes

Comment memset initialise un tableau d'entiers par -1 ?

El page d'accueil dit à propos de memset :

#include <string.h>
void *memset(void *s, int c, size_t n)

El memset() remplit le premier n octets de la zone de mémoire pointée par s avec l'octet constant c .

Il est évident que memset ne peut pas être utilisé pour initialiser int comme indiqué ci-dessous :

int a[10];
memset(a, 1, sizeof(a));  

c'est parce que int est représenté par 4 octets (disons) et on ne peut pas obtenir la valeur désirée pour les entiers dans le tableau a .
Mais je vois souvent les programmeurs utiliser memset pour définir le int à l'un ou l'autre des éléments du tableau 0 o -1 .

int a[10];
int b[10];
memset(a, 0, sizeof(a));  
memset(b, -1, sizeof(b));  

D'après ce que j'ai compris, l'initialisation avec des entiers 0 est OK parce que 0 peut être représenté par un octet (je me trompe peut-être dans ce contexte). Mais comment est-il possible d'initialiser b con -1 (une valeur de 4 octets) ?

25 votes

Downvoter, vous pouvez expliquer ? Cette question n'est-elle pas pertinente pour ce site ou pour autre chose ?

0 votes

Vous avez légèrement tort quant à la raison pour laquelle l'initialisation avec 0 est OK. C'est OK parce que 0 s'insère dans un unsigned char (afin qu'il ne soit pas tronqué lorsqu'il est utilisé comme deuxième argument de la fonction memset ) y car la configuration binaire en mémoire pour un sizeof(int) -L'octet zéro est identique à la configuration binaire en mémoire pour l'octet zéro. sizeof(int) des zéros séquentiels d'un octet. Ces deux choses doivent être vraies pour que cela fonctionne. En fait, ces choses sont vraies pour exactement deux nombres en arithmétique à deux compléments : 0 y -1 .

0 votes

@zwol : Hmm ? La première phrase parle de zéros et n'est donc pas littéralement vraie pour 1. Donc on peut supposer que vous avez l'intention de paramétrer implicitement la première phrase : Cela fonctionne pour x si les bits d'un int avec valeur x sont les mêmes que les bits pour sizeof(int) unsigned char chacun ayant la valeur x . De plus, nous devons considérer le unsigned char avec valeur x comme résultant de la conversion de x a unsigned char car 1 n'est pas représentable. Si c'est le cas, alors il n'est pas vrai que 0 et 1 sont les seules valeurs de ce type. 16,843,009 - x fonctionne pour tout nombre entier 0 x < 256. (16,843,009 est hex 1010101).

74voto

dasblinkenlight Points 264350

Bizarrement, la raison pour laquelle cela fonctionne avec -1 est exactement la même que la raison pour laquelle cela fonctionne avec des zéros : en représentation binaire en complément à deux , -1 tiene 1 dans tous ses bits, quelle que soit la taille de l'entier, donc remplir une région avec des octets remplis de tous les 1 produit une région de -1 signé int s, long et short sur le matériel de complément à deux.

Sur un matériel qui diffère du complément à deux, le résultat sera différent. Le site -1 La constante entière serait convertie en un unsigned char de tous, car la norme est spécifique sur la façon dont la conversion doit être effectuée. Cependant, une région d'octets dont tous les bits sont à la valeur 1 seraient interprétés comme des valeurs intégrales conformément aux règles de la plate-forme. Par exemple, sur un matériel à signe et magnitude, tous les éléments de votre tableau contiendront la plus petite valeur négative du type correspondant.

17 votes

N'utiliserait-on pas ~0 sont effectivement les mêmes (et plus claires) ?

2 votes

@FiddlingBits Oui, en utilisant ~0 éviterait définitivement la confusion ici.

0 votes

J'ai compris votre réponse mais pouvez-vous expliquer cette ligne : Ainsi, le remplissage d'une région avec -1 octet produit une région de -1 ints, longs et courts signés. ?

8voto

Minhas Kamal Points 5582

Quand tous les bits d'un nombre sont 0 sa valeur est également 0 . Cependant, si tous les bits sont 1 la valeur est -1 .

Si nous écrivons int a[2] , 4x2 octets de mémoire sont alloués qui contiennent des bits aléatoires/arbitraires-

00110000 00100101 11100011 11110010    11110101 10001001 00111000 00010001

Alors, nous écrivons memset(a, 0, sizeof(a)) . Maintenant, memset() fonctionne octet par octet, et la représentation d'un octet ( unsigned char ) de 0 es 00000000 . Donc, ça devient

00000000 00000000 00000000 00000000    00000000 00000000 00000000 00000000

Par conséquent, les deux a[0] y a[1] sont initialisés avec 0 .


Maintenant, voyons memset(a, -1, sizeof(a)) : un octet pour -1 es 11111111 . Et, on a

11111111 11111111 11111111 11111111    11111111 11111111 11111111 11111111

Ici, les deux a[0] y a[1] aura la valeur -1 .


Toutefois, pour memset(a, 1, sizeof(a)) : 1 dans un octet est 00000001 -

00000001 00000001 00000001 00000001    00000001 00000001 00000001 00000001

Donc, la valeur sera 16843009 .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X