6
votes

Pourquoi le Winapi utilise-t-il un Int (32 bits) pour le type BOOL?

// <windef.h>

typedef int                 BOOL;
Isn't this a waste of memory since an int is 32 bits?Just in case I was wrong, I tried sending a normal bool* to a function that required BOOL* and didn't work until I used the typedef int.

12 commentaires

Une fois une fois, bool n'était pas de type C. Voir Stackoverflow.com/questions/1608318/is -bool-a-native-c-type


Oman je suis tellement dum je suis vrai dum pour de vrai


Je savais que Bool a été ajouté à C alors qu'est-ce que le HoldUp ici


Savez-vous combien de temps que celui-ci a été là?


Je suppose que la compatibilité binaire. Les anciens programmes s'attendent à ce que l'API prenne et retourne 4 octets, pas Bool.


Parfois, BOOL est utile, dans. Qu'est-ce qui est en outre vrai et faux, vous voulez avoir un état indéterminé - puis la définir à -1


@Luskan jamais jamais jamais jamais faire ça. Quelqu'un qui est habitué à un Sane Bool de 1/0 sera royalement vissé lorsque votre -1 est interprété par le programme comme vrai. Si vous devez faire quelque chose comme ça, utilise un nom différent et en faites un énumé.


@Jonathonreinhart pfft. Je semble qu'ils le font sur TheDailywtf.com tout le temps. Prenez l'affaire File_Not_found utile, par exemple ... ;-) Mais pour de vrai, certains Winapi (ou ce que cela vb6?) Utilise une troquerie, je pense ...?


Ne me trompe pas, j'utilise bool? en C # tout le temps. Parfois, vous ne savez si quelque chose est vrai ou faux encore. Mais, bool? ne peut pas être jeté sur bool , de sorte que le compilateur vous empêche de faire quelque chose de stupide.


@Jonathonreinhart non, non, je suis tout à fait d'accord avec vous entièrement ;-) Mais je crois que le retour d'un "non booléen" existe réellement dans certaines des choses Winapi ... ou j'ai eu un mauvais cauchemar et c'est tout ce que je peux " rappelles toi".


@JonathonReinhart Je suis d'accord, en utilisant Enum serait la solution préférée, au moins cela aurait l'air mieux, mais cela ne protégerait toujours pas quelqu'un d'écrire quelque chose comme: Enum nullablebool {nb_t, nb_f, nb_n} nb = nb_n; Si (NB) {/ * Opps! * /}


@luskan tu as raison. En C, le compilateur ne peut vous protéger que de vous dans une mesure limitée. Parfois, vous devez faire attention! Mais au moins cela vous empêche de définir un piège pour les autres à l'avenir.


5 Réponses :


19
votes

wow, ralentissez un peu là-bas. Tout d'abord, je suis à peu près sûr que les programmeurs utilisent 4 octets int S pour les variables booléennes depuis le début de la programmation sur x86. (Il n'y avait pas d'autre chose qu'un BOOL DataType). Et j'avais aveuver de deviner que ce même typé est dans Windows 3.1 .

Deuxièmement, vous devez comprendre un peu plus sur l'architecture. Vous avez une machine 32 bits, ce qui signifie que tous les registres de la CPU sont de 4 octets ou de 32 bits de large. Donc, pour la plupart des accès à la mémoire, il est plus efficace à stocker et à accéder aux valeurs de 4 octets que pour une valeur de 1 octet.

Si vous avez quatre variables booléennes de 1 octete emballées dans une pièce de mémoire de 4 octets, trois de ceux-ci ne sont pas dadors (4 octets) alignés. Cela signifie que le contrôleur CPU / Memory doit effectivement faire plus travail pour obtenir la valeur.

et avant de vous briser sur la SM pour avoir créé ce "gaspillage" Typef. Considérez ceci: sous la hotte, la plupart des compilateurs (probablement) immobilisent le type bool DataType en tant que 4 octets int pour les mêmes raisons pour lesquelles je viens de mentionné. Essayez-le dans GCC et jetez un coup d'œil au fichier de carte. Je parie que j'ai raison.


3 commentaires

Cela, les problèmes d'alignement avec 1 octet sont horribles avec un registre de taille standard.


Sur X86, cependant, il est aussi facile d'obtenir 1 octet tel qu'il est 4. Les problèmes d'alignement entrent en jeu lorsque vous avez des valeurs multi-octets. L'inefficacité majeure est que vous lisez 4 octets lorsque je ferai ... mais de toute façon, il faut le même temps.


L'argument historique est valide, le reste n'est pas. GCC produit un 1 octet bool. Chargement / stockage 1 octet est définitivement différent au niveau de la puce et a des implications différentes pour la mise en cache, l'alignement et la concurrence que de charger 4 octets.



2
votes

Le processeur est 32 bits et dispose d'un drapeau spécial lorsqu'il fonctionne sur un entier nul, effectuant des tests pour des valeurs booléennes 32 bits très vite.

Test pour un 1 bit ou une valeur booléenne d'octete va être plusieurs fois plus lent.

Si vous êtes inquiet pour l'espace mémoire, vous pourriez vous inquiéter d'environ 4 variables BOLE BOOL.

La plupart des programmeurs, cependant, sont plus inquiets pour les performances et, par conséquent, la valeur par défaut est d'utiliser le bool 32 bits plus rapide.

Vous pourrez peut-être obtenir votre compilateur pour optimiser l'utilisation de la mémoire si cela vous dérange.


2 commentaires

@chao Oui, mais vous devez faire plus de travail à obtenir cet octet de la mémoire. Vous devez tirer au moins 32 bits et le masquer.


De plus, la plupart des X86 cpus ces jours-ci - 32 bits! - Avoir des bus de données de 64 bits (Intel le faisait-il depuis P6, je crois ... peut-être même le Pentium original), de sorte que le masquage et / ou le déplacement desseraient toujours besoin de faire.



13
votes

Premièrement, le type utilisé dans l'API système doit être aussi indépendant de la langue que possible, car l'API sera utilisée par une multitude de langages de programmation. Pour cette raison, tout type "conceptuel" qui pourrait n'existerait pas dans certaines langues ou pourrait être mis en œuvre différemment dans d'autres langues étant hors de question. Par exemple, bool correspond à cette catégorie. En plus de cela, dans une API système, il est une bonne idée de conserver au minimum le nombre de types d'interface. Tout ce qui peut être représenté par int doit être représenté par int .

Deuxièmement, votre affirmation à ce sujet est "un gaspillage de mémoire" n'a aucun sens que ce soit. Afin de devenir "un gaspillage de mémoire", il faudrait construire un type de données agrégé qui implique un nombre extrêmement grand de bool . Windows API n'utilise aucun type de données de ce tel. Si vous avez construit un tel type de données inutile dans votre programme, c'est en fait votre faute. Pendant ce temps, Windows API ne vous oblige en aucun cas à stocker vos valeurs booléennes dans BOOL type. Vous pouvez utiliser des octets et même des bits à cette fin. En d'autres termes, bool est une interface purement . Objet de bool Normalement n'occuper aucune mémoire à long terme du tout, si vous l'utilisez correctement.


2 commentaires

@DYP: Pas vraiment. AFAIK Il y a des langues existantes qui ne prennent pas en charge 1 types d'octets tout simplement parce qu'ils n'ont aucune raison de.


J'aime toujours vraiment la façon dont vous avez expliqué cela. Nous traitons avec une API , pas une structure de données.



3
votes

Historiquement BOOL CODE> a été utilisé comme un Not-0 i> = TRUE TYPE. Par exemple, une procédure de dialogue renvoya un bool code>, qui pourrait contenir beaucoup d'informations. La signature ci-dessous est de Microsoft Documentation :

INT_PTR CALLBACK DialogProc(
    _In_  HWND hwndDlg,
    _In_  UINT uMsg,
    _In_  WPARAM wParam,
    _In_  LPARAM lParam
);


0 commentaires

0
votes

La plupart des réponses ici semblent être mal informées. L'utilisation de 4 octets pour une valeur booléenne n'est pas plus rapide que d'utiliser 1 octet. L'architecture X86 peut lire 1 octet aussi vite que possible 4, mais 1 octet est moins de mémoire. L'utilisation de la mémoire est l'une des plus grandes menaces pour la performance. Utilisez trop de mémoire et vous aurez plus de cache Misses, et vous aurez un programme plus lent. Ce genre de choses n'a pas d'importance si vous ne traitez qu'une poignée (centaines!) De booléens, mais si vous en avez une tonne, l'utilisation de moins de mémoire est la clé de la performance supérieure. Dans le cas d'une matrice massive, je recommanderais 1 bit au lieu de 1 octet, car la logique supplémentaire pour masquer ce bit est sans conséquence si elle économise 87% de mémoire. Vous voyez cette pratique beaucoup avec le drapeau bitfields.

La réponse à la question est la plus définitive "des raisons héritées". C'est-à-dire "Ne touchez pas les choses qui ne sont pas cassées." Changer une ligne de code comme pour une optimisation mineure pourrait introduire des centaines d'autres problèmes que personne ne veut traiter.


0 commentaires