2010-01-19 4 views
2

J'ai deux tâches pour une affectation, une retourne le nombre de bits de type int sur n'importe quelle machine. Je pensais que je voulais écrire ma fonction comme ceci:Nombre de bits dans un type de données

int CountIntBitsF() { 
    int x = sizeof(int)/8; 
    return x; 
} 

Est-ce correct?

La deuxième partie consiste à renvoyer le nombre de bits de n'importe quel type de données avec une macro, et la macro peut être extraite de limits.h. J'ai regardé limites.h sur ma machine, et aussi http://www.opengroup.org/onlinepubs/007908799/xsh/limits.h.html, mais je ne pense pas que je comprenne vraiment comment l'un d'eux retournerait le nombre de bits dans n'importe quel type de données. Des pensées? Merci.

+0

Question connexe: [c - Nombre de bits dans le type de données de base] (http://stackoverflow.com/questions/19244371/). –

Répondre

6

C'est *, pas /. Pour la deuxième partie, voir la section «Limites numériques».

3

En limits.h, UINT_MAX est la valeur maximale pour un objet de type unsigned int. Ce qui signifie qu'il est un entier avec tous les bits à 1. Ainsi, en comptant le nombre de bits dans un entier:

#include <limits.h> 

int intBits() { 
    int x = INT_MAX; 
    int count = 2; /* start from 1 + 1 because we assume 
        * that sign uses a single bit, which 
        * is a fairly reasonable assumption 
        */ 

    /* Keep shifting bits to the right until none is left. 
    * We use divide instead of >> here since I personally 
    * know some compilers which does not shift in zero as 
    * the topmost bit 
    */ 
    while (x = x/2) count++; 

    return count; 
} 
+0

De tels compilateurs violent la norme, fwiw. –

+0

@slebetman: vous pensez peut-être à changer les valeurs * signées *. Pour les types non signés, le décalage est bien défini. –

+0

Je pense qu'il y a une certaine confusion ici si x devrait être non signé ou signé. La question porte sur 'int', auquel cas le commentaire sur le décalage serait justifié, mais pour une raison quelconque, cette réponse concerne un entier non signé. –

1

Êtes-vous sûr que vous voulez nombre de bits, et non le nombre d'octets? En C, pour un type donné T, vous pouvez trouver le nombre d'octets qu'il prend en utilisant l'opérateur . Le nombre de bits dans un octet est CHAR_BIT, ce qui est généralement 8, mais peut être différent.

Ainsi, étant donné un type T, le nombre de bits dans un objet de type T est:

#include <limits.h> 
size_t nbits = sizeof(T) * CHAR_BIT 

Notez que, sauf pour le type unsigned char, toutes les combinaisons possibles de nbits les bits ci-dessus peuvent ne pas représenter valide valeur du type T.

Pour la deuxième partie, notez que vous pouvez appliquer l'opérateur sizeof à un objet ainsi qu'à un type. En d'autres termes, étant donné un type T et un objet x de ce type:

T x; 

Vous pouvez trouver la taille de T par sizeof(T), et la taille de x par sizeof x. Les parenthèses sont facultatives si sizeof est utilisé pour un objet. Compte tenu des informations ci-dessus, vous devriez être en mesure de répondre à votre deuxième question. Demandez à nouveau si vous avez encore des problèmes.

2

Si vous voulez le nombre de bits utilisés pour stocker un int en mémoire, utilisez la réponse de Justin, sizeof(int)*CHAR_BIT. Si vous voulez connaître le nombre de bits utilisés dans la valeur, utilisez la réponse de slebetman.

Bien que pour obtenir les bits dans un INT, vous devriez probablement utiliser INT_MAX plutôt que UINT_MAX. Je ne me souviens pas si C99 garantit réellement que int et unsigned int ont la même largeur, ou juste qu'ils ont la même taille de stockage. Je suspecte seulement ce dernier, puisque dans 6.2.6.2 nous avons "s'il y a M bits de valeur dans le type signé et N dans le type non signé, alors M < = N", pas "M = N ou M = N-1" .

En pratique, les types entiers n'ont pas de bits de remplissage dans les implémentations que j'ai utilisées, donc vous obtiendrez probablement la même réponse pour tous, +/- 1 pour le bit de signe.

+2

Autre citation du projet C99 (6.2.5.6): Pour chacun des types entiers signés, il existe un type entier non signé correspondant (mais différent) (désigné par le mot clé 'unsigned') qui utilise la même quantité de stockage (y compris le signe informations) et a les mêmes exigences d'alignement. –

+1

Merci. Et notez "même quantité de stockage", ne pas dire "même nombre de bits non-padding". –

+0

Pourquoi avons-nous besoin de connaître la différence entre un int en mémoire et les bits utilisés dans la valeur. Les bits utilisés dans la valeur sont-ils plus importants si vous faisiez une sorte de programmation matérielle où vous deviez connaître le nombre de bits utilisés pour représenter certaines valeurs de registre ou quelque chose le long de ces lignes? – Crystal

2

Avec g ++ -O2 cette fonction évalue une constante ligne:

#include <climits> 
#include <stddef.h> 
#include <stdint.h> 
#include <cstdio> 

template <typename T> 
size_t num_bits() 
{ 
    return sizeof (T) * (CHAR_BIT); 
} 

int main() 
{ 
    printf("uint8_t : %d\n", num_bits<uint8_t>()); 
    printf("size_t : %d\n", num_bits<size_t>()); 
    printf("long long : %d\n", num_bits<long long>()); 
    printf("void* : %d\n", num_bits<void*>()); 
    printf("bool : %d\n", num_bits<bool>()); 
    printf("float : %d\n", num_bits<float>()); 
    printf("double : %d\n", num_bits<double>()); 
    printf("long double : %d\n", num_bits<long double>()); 

    return 0; 
} 

sorties:

uint8_t : 8 
size_t : 32 
long long : 64 
void* : 32 
bool : 8 
float : 32 
double : 64 
long double : 96 

Création X86 32 bits Assember:

--- --- SNIP

movl $32, 8(%esp)  <--- const $32 
movl $.LC1, 4(%esp) 
movl $1, (%esp) 
call __printf_chk 
movl $64, 8(%esp)  <--- const $64 
movl $.LC2, 4(%esp) 
movl $1, (%esp) 
call __printf_chk 

--- SNIP ---

Questions connexes