51 votes

Obtenir bool de C à C++ et à l'arrière

Lors de la conception de structures de données qui doivent être transmises par le biais d'une API en C qui relie code C et C++, est-il sécuritaire d'utiliser bool? C'est, si j'ai un struct comme ceci:

struct foo {
  int bar;
  bool baz;
};

est-il garanti que la taille et le sens de l' baz ainsi que sa position dans foo sont interprétés de la même manière par C (où c'est un _Bool) et en C++?

Nous envisageons pour ce faire sur une seule plate-forme (GCC pour Debian 8 sur un Beaglebone) avec à la fois le C et le C++ le code compilé par la même version de GCC (C99 et C++11, respectivement). Général les commentaires sont les bienvenus, bien que.

50voto

Paulo Torrens Points 207

De C et de C++' bool type sont différents, mais, aussi longtemps que vous vous en tenez à la même compilateur (dans votre cas, gcc), il devrait en être sûre, que c'est raisonnable scénario commun.

En C++, bool a toujours été un mot-clé. C n'en avais pas jusqu'à ce que le C99, où ils ont introduit le mot-clé _Bool (parce que les gens utilisés pour la définition de type ou #define bool comme int ou char en C89 code, donc directement l'ajout de bool en tant que mot clé de casser le code existant); il est l'en-tête stdbool.h qui devrait, en C, ont une définition de type ou n ° de définir à partir de _Bool de bool. Jetez un oeil à la vôtre; GCC de la mise en œuvre ressemble à ceci:

/*
 * ISO C Standard:  7.16  Boolean type and values  <stdbool.h>
 */

#ifndef _STDBOOL_H
#define _STDBOOL_H

#ifndef __cplusplus

#define bool        _Bool
#define true        1
#define false        0

#else /* __cplusplus */

/* Supporting <stdbool.h> in C++ is a GCC extension.  */
#define _Bool        bool
#define bool        bool
#define false        false
#define true        true

#endif /* __cplusplus */

/* Signal that all the definitions are present.  */
#define __bool_true_false_are_defined        1

#endif        /* stdbool.h */

Ce qui nous conduit à penser que, au moins dans GCC, les deux types sont compatibles (à la fois la taille et l'alignement, de sorte que la structure de mise en page restera le même).

A noter également, l' Itanium ABI, qui est utilisé par la GCC et la plupart des autres compilateurs (à l'exception de Visual Studio; comme l'a noté M. Matthieu dans les commentaires ci-dessous) sur de nombreuses plates-formes, spécifie que _Bool et bool suivre les mêmes règles. C'est une forte garantie. Un troisième indicateur, nous pouvons obtenir est de l' Objective-C manuel de référence de l', qui dit que l'Objective-C et Objective-C++, où le respect de C et de C++de conventions respectivement, bool et _Bool sont équivalentes; donc je serais assez bien dire que, si les normes ne garantit pas cela, vous pouvez supposer que oui, ils sont équivalents.

Edit:

Si la norme ne garantit pas qu' _Bool et bool seront compatibles (dans la taille, l'alignement, et le rembourrage), qu'est-ce?

Quand nous disons que ces choses sont "dépendants de l'architecture", nous voulons dire qu'ils sont ABI dépendante. Chaque compilateur met en œuvre un ou plusieurs ABIs, et deux compilateurs (ou versions d'un même compilateur) sont compatibles s'ils mettent en œuvre la même ABI. Depuis, il est prévu d'appeler du code C à partir de C++, c'est ubiquitaire commun, tous C++ ABIs j'ai jamais entendu parler d'étendre le local C ABI.

Depuis l'OP posé sur Beaglebone, nous devons vérifier les BRAS ABI, et plus particulièrement de la GNU ARM EABI utilisé par Debian. Comme indiqué par Justin Time dans les commentaires, le BRAS ABI, en effet, déclare C++'ABI d'étendre C, et qui en _Bool et bool sont compatibles, les deux étant de taille 1, l'alignement 1, représentant une machine octet non signé. Donc la réponse à la question, sur la Beaglebone, oui, _Bool et bool sont compatibles.

16voto

Art Points 6040

Les normes linguistiques ne rien dire sur ce sujet (je suis heureux d'avoir tort sur ce sujet, je ne pouvais pas trouver quoi que ce soit), donc il ne peut pas être sûr si on se contente de nous limiter à des normes linguistiques. Mais si vous êtes pointilleux sur les architectures de vous soutenir, vous pouvez trouver leur ABI documentation pour voir si elle sera en sécurité.

Par exemple, l' amd64 ABI document est une note de bas de page pour l' _Bool type qui dit:

On appelle ce type bool en C++.

Que je ne peux pas interpréter autrement que de la manière qu'il sera compatible.

Aussi, il suffit de réflexions à ce sujet. Bien sûr, il fonctionnera. Les compilateurs de générer du code qui à la fois suivre un ABI et le comportement de la plus grande compilateur pour la plate-forme (si ce comportement est hors de l'ABI). Une grande chose au sujet de C++, c'est qu'il peut lier à des bibliothèques écrites en C et une chose à propos des bibliothèques, c'est qu'ils peuvent être compilé par un compilateur sur la même plate-forme (c'est pourquoi nous avons ABI documents dans la première place). Peut-il y avoir une incompatibilité mineure à un certain point? Bien sûr, mais c'est quelque chose que vous feriez mieux de le résoudre par un rapport de bug pour le compilateur maker plutôt que de la solution de contournement dans votre code. Je doute bool serait quelque chose compilateur décideurs serait gâcher.

6voto

Gill Bates Points 3884

La seule chose que le C standard dit sur _Bool :

Un objet déclaré comme étant de type _Bool est assez grand pour stocker les valeurs 0 et 1.

Ce qui veut dire qu' _Bool est au moins sizeof(char) ou plus (donc true / false sont garantis d'être stockable).

La taille exacte est la mise en œuvre définie comme Michael a dit dans les commentaires. Vous êtes mieux de simplement effectuer quelques tests sur leurs tailles sur le compilateur, et si ces match et vous restez avec le même compilateur, je considère qu'il est sécuritaire.

6voto

Graham Points 461

Comme Gill Bates dit ci-dessus, vous avez un problème qu' sizeof(bool) du compilateur est-dépendante. Il n'y a aucune garantie que le même compilateur traitera de la même façon. Les compilateurs ont souvent une option pour réduire la longueur des enums si les valeurs définies pour le dénombrement peut être monté dans un plus petit nombre de bits, et il ne serait pas inattendu pour bool d'être traité de cette façon. Le compilateur pourrait même être à l'intérieur de ses droits (selon la norme C) pour représenter cela comme un individu peu dans un champ de bits s'il le voulait.

J'ai personnellement vécu ce moment de travailler avec le TI OMAP-L138 processeur qui combine un 32-bit ARM de base et un 32-bit DSP de base sur le même appareil, avec une part de mémoire accessible par les deux. Le BRAS de base représentée bool comme int (32 bits ici), alors que la DSP représentée bool comme char (8 bits). Pour résoudre cela, j'ai défini mon propre type bool32_t pour une utilisation avec l'interface de mémoire partagée, sachant qu'une valeur de 32 bits à travailler pour les deux côtés. Bien sûr, je pourrais avoir définie comme une valeur de 8 bits, mais je considère que c'est moins susceptibles d'affecter les performances si je l'ai gardé que le natif d'entiers de taille.

Si vous faites de même, comme je le faisais alors vous pouvez garantir à 100% la compatibilité binaire entre votre code C et C++. Si vous n'avez pas, alors vous ne pouvez pas. C'est vraiment aussi simple que cela. Avec le même compilateur, vos chances sont très bonnes mais il n'y a aucune garantie, et de changer les options du compilateur peut facilement les vis que vous avez plus de façon inattendue.

Sur un sujet connexe, votre int devrait également être l'aide d' int16_t, int32_t ou un autre nombre entier de taille définie. (Vous devez inclure stdint.h de ces définitions de type.) Sur la même plate-forme, il est très peu probable que ce sera différent pour le C et le C++, mais c'est une odeur de code pour le firmware à utiliser int. L'exception est dans les endroits où vous avez vraiment ne se soucient pas combien de temps un int , mais il devrait être clair que les interfaces et les structures doivent avoir que bien définies. Il est trop facile pour les programmeurs de faire des hypothèses (qui sont souvent erronés!) au sujet de sa taille, et les résultats sont généralement catastrophique quand ça se passe mal, et pire, ils n'ont souvent pas aller mal dans les essais où vous pouvez facilement trouver et de les corriger.

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