Dernier " n " bits unsigned int
Comment définir (dans la plupart de manière élégante) exactement n
bits de poids faible de uint32_t
? C'est-à-écrire une fonction void setbits(uint32_t *x, int n);
. La fonction doit gérer chaque n
de 0
à 32
.
Surtout de la valeur n==32
doivent être manipulés.
- en dernière voulez-vous dire d'ordre élevé ou faible?
- cette question gère toutes les valeurs dans l'intervalle [0, 64]: Créer un masque avec N bits de poids faible set
Vous devez vous connecter pour publier un commentaire.
Si vous voulez dire le moins significatif n bits:
Sur la plupart des architectures, cela ne marchera pas, si n est de 32, de sorte que vous pourriez avoir à faire un cas particulier pour que:
Sur une architecture 64 bits, un (probablement) solution plus rapide consiste à jeter vers le haut puis vers le bas:
En fait, cela pourrait même être plus rapide sur une architecture 32 bits, car elle évite la ramification.
((uint32_t)-1)>>(32-n)
😉1
est de typeint
et1 << n
qui pourrait aller mal pour beaucoup plus de cas que vous ne le supposez. Un premier coup serait d'utiliser1U << n
mais alors l'OP explicitement vouluuint32_t
. Pour que la bonne chose serait d'utiliserUINT32_C(1) << n
.(uint32_t)((-1)>>(32-n))
(uint32_t)
, signé il va rester avec tous les bits définis pour toutes les valeurs de n.31
sur un entier de 32 bits, conduit à débordement => un comportement indéfini. Et puisint
n'est garanti que pour être de 16 bits de large par la norme. En résumé votre version peut échouer pour des valeurs de16
à31
.n
àuint64_t
? Vous devez "fonte" la1
c'est ce qui détermine le type de l'expression.cond?a:b
les cas de ce genre. Essayez de compiler en assemblée et vérification de la sortie.1U
au lieu de1
comme base de la maj.~0UUL
ou~0UL
au lieu de0xsomanyf
. Ça va être plus indépendant de la plateforme que vous n'avez pas besoin de connaître la taille exacte deint
oulong
ou quoi que ce soit.Voici une méthode qui ne nécessite pas d'arithmétique:
uint_32t
par32
est un comportement indéterminé.Les autres réponses ne gèrent pas le cas spécial de
n == 32
(décalage par supérieure ou égale à la type largeur de l'UB), voici donc une meilleure réponse:Sinon:
UINT64_C(1)
. Et puis, votre solution ne fonctionne pas sur des architectures avec 16 bitsint
, mais ne fonctionne pas pour la version 32 bitsint
soit, parce que pour31
vous avez un dépassement de capacité.(uint64_t)1
?Si tu veux dire que le plus important n bits:
Si n est égal à zéro alors pas de bits doivent être fixés sur la base de la question.
Objectifs:
Remarque: si vous avez besoin d'
n
pour être de typeint
, ajoutez ceci à la fin:Explication:
Quand
n>=32
est vrai,x
sera au niveau du bit-par un ou binaire avec 0xFFFFFFFF, ce qui donne unx
avec tous les bits définis.Cette ligne indique qu'aussi longtemps que les bits doivent être fixées,
n>0
, au niveau du bit ETx
avec 0xFFFFFFFF qui n'apportera aucun changement àx
. Sin<=0
,x
sera au niveau du bit-ANDed avec 0 et, donc, une valeur de 0.Exemple de programme pour montrer que l'algorithme fonctionne:
De sortie (cassé et annoté):
Pour
n < = 0
, la dernière étape de l'ANDs avec 0 garantir le résultat est 0.Pour
1 <= n <= 31
, les deux dernières étapes "OU 0, ET la valeur 0xffffffff" provoque aucun changement à ce numéro. La seule étape qui compte, c'est le "OU (1<Pour
n >= 32
, tous les bits doivent être définis, et les "OU ffffffff" étape accomplit que, indépendamment de ce que l'étape précédente a pu faire. Len <= 0
étape est alors un noop ainsi avecAND ffffffff
.n >= 32
n'aide pas, car l'état de la case à cocher passage sera toujours fait, et sin >= sizeof(TheType) * CHAR_BIT
, c'est UB, ce qui n'est pas affectée par le fait que vous essayez de papier au-dessus d'elle après le fait.n>=32
parce que la ligne suivante corrige. J'ai ajouté un programme à la réponse qui prouve que l'algorithme. Honnêtement, ça a été tellement long que j'avais besoin de ce programme pour le prouver à moi-même.x = uint32_t(1) << 40; x = 7;
Même si la première affirmation est un comportement indéfini (pour certaines valeurs, par exemple, 40), la deuxième ligne est très bien défini le comportement et le résultat est ok. Sauf si "un comportement indéfini" comprend plantage d'une application, ou de corruption de la mémoire, il est bon.<<
ne veut pas dire maj pour mon compilateur. Il signifie clairement le décalage avec la rotation qui je n'aurais pas cru (comportement indéfini).Dernier n bits. n doit être > 0. Travailler avec n = 32.
La fonction avec un test simple: