2017-05-10 2 views
1

Inspiré de cette question, j'ai:Attention sur un seul bitfield, au lieu des deux?

#include<stdio.h> 
struct st 
{ 
     int a:1; 
     int b:2; 
}; 

int main() 
{ 
     struct st obj={1, 2}; 
     printf("a = %d\nb = %d\n",obj.a,obj.b); 
} 

et je reçois:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c 
main.c:10:26: warning: implicit truncation from 'int' to bitfield changes value 
     from 2 to -2 [-Wbitfield-constant-conversion] 
     struct st obj={1, 2}; 
         ^
1 warning generated. 
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
a = -1 
b = -2 

Je pense que je comprends pourquoi les deux bitfields ne parviennent pas à tenir leurs valeurs (selon ce answer), mais je ne ne comprends pas pourquoi le compilateur avertit sur 2 seulement, au lieu de 1 aussi! Des idées?

J'utilise dans mon Mac:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -v 
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 
Apple LLVM version 8.1.0 (clang-802.0.38) 
Target: x86_64-apple-darwin16.3.0 
Thread model: posix 
InstalledDir: /Library/Developer/CommandLineTools/usr/bin 

Dans un ancien système Linux, avec la version gcc 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5), je suis pas d'avertissement connexe.

Dans une installation Debian, avec gcc version 4.9.2 (Debian 4.9.2-10), je n'ai reçu aucun avertissement associé!

+0

fyi g ++ 5.1.0 produit les 2 avertissements comme prévu. 2 * 'avertissement: débordement dans la conversion constante implicite [-Woverflow]' –

Répondre

1

https://en.wikipedia.org/wiki/Two%27s_complement

Il pourrait y avoir une ou deux choses qui se passent, des expériences peuvent peut-être aider. Tout d'abord, il se peut que gcc soit assez intelligent pour savoir qu'un seul bit ne peut pas être réellement positif ou négatif, car il ne s'agit que d'un seul bit.

L'autre possibilité est l'ordre dans lequel gcc évalue qu'une expression est en arrière de ce que vous pensez. Certains compilateurs évaluent de droite à gauche et dans votre cas, ont expulsé l'erreur et ont arrêté.

Pour tester, corrigez le champ de bits pour que b contienne un entier signé pour '2' sans retourner le bit de signe (3 bits devraient fonctionner). Si en fixant 'b' vous avez généré une erreur pour 'a', alors vous savez que c'est juste l'ordre d'évaluation du compilateur.

Si la correction 'b' n'entraîne pas le lancement d'un avertissement par 'a', alors gcc effectue une optimisation interne sur un champ à un seul bit. De plus, changer vos types de champs de bits en 'uint' devrait aussi fixer les avertissements, auquel cas c'est simplement le bit de signe de la représentation qui est retourné.

Bonne codification.

EDIT code source pertinente: https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaChecking.cpp#L8812

+0

Lorsque je corrige 'b', je n'obtiens aucun avertissement pour' a'. . .Mais +1 pour l'idée! – gsamaras

+0

Cool. Je mettrais probablement de l'argent sur gcc ayant une spécialisation pour un seul bit. En C++, ceci est fait en utilisant une spécialisation de template partielle, et I * think * gcc est écrit en C++. –

+1

J'ai trouvé le code source vérifier pour clang ici: https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaChecking.cpp#L8812 –

0

int b:2; est un entier signé de largeur de 2 bits. Le numéro 2 (non signé) est représenté sous la forme 10 en binaire et parce que la source int est signée, vous obtenez réellement le numéro signé enregistré dans la mémoire.

C'est la raison pour laquelle vous avez reçu cet avertissement.

Les valeurs que vous pouvez enregistrer 2 bits signé int sont: (-2 = 11, -1 = 10, 0 = 00, 1 = 01)

Raison pour laquelle vous n'avez pas dans les deux cas est que int a:1 est seulement 1 bit et peut contenir des numéros 1 ou 0, sans nombres négatifs.

+0

Merci pour la réponse, mais la question est pourquoi je n'ai pas reçu les deux avertissements! :) – gsamaras

+0

Désolé, mise à jour de la réponse ci-dessus. – tilz0R

+0

Mais si c'est le cas, je m'attendrais à 1 à être imprimé. Voir, la question liée initiale pour plus s'il vous plaît. – gsamaras