J'ai récemment découvert un problème ennuyeux dans un grand programme que je développe; Je voudrais comprendre comment le réparer de la meilleure façon. J'ai réduit le code à l'exemple minimal suivant.Constantes intégrales C++ + opérateur de choix = problème!
#include <iostream>
using std::cin;
using std::cout;
class MagicNumbers
{
public:
static const int BIG = 100;
static const int SMALL = 10;
};
int main()
{
int choice;
cout << "How much stuff do you want?\n";
cin >> choice;
int stuff = (choice < 20) ? MagicNumbers::SMALL : MagicNumbers::BIG; // PROBLEM!
cout << "You got " << stuff << "\n";
return 0;
}
Je reçois des erreurs de lien dans gcc 4.1.2 lors de la compilation avec -O0 ou -O1 mais tout est OK lors de la compilation avec -O2 ou -O3. Il lie bien en utilisant MS Visual Studio 2005 sans tenir compte des options d'optimisation.
test.cpp:(.text+0xab): undefined reference to `MagicNumbers::SMALL'
test.cpp:(.text+0xb3): undefined reference to `MagicNumbers::BIG'
I regardé le code d'assemblage intermédiaire, et oui, le code non optimisé considéré petit et grand int en tant que variables externes, tandis que l'optimisation utilise une des nombres réels. Chacune des modifications suivantes résout le problème:
utilisation enum au lieu d'int pour les constantes:
enum {SMALL = 10}
Cast la constante (quelconque) à chaque usage:
(int)MagicNumbers::SMALL
ou(int)MagicNumbers::BIG
ou mêmeMagicNumbers::SMALL + 0
Utiliser une macro:
#define SMALL 10
Ne pas utiliser l'opérateur de choix:
if (choice < 20) stuff = MagicNumbers::SMALL; else stuff = MagicNumbers::BIG;
J'aime la première option meilleure (cependant, ce n'est pas idéal parce que nous utilisons en fait uint32_t au lieu de int pour ces constantes et ENUM est synonyme int). Mais ce que je veux vraiment demander est: à qui le bug est-il? Est-ce que je suis responsable de ce que je ne comprends pas comment fonctionnent les constantes intégrales statiques? Dois-je accuser gcc et espérer un correctif (ou peut-être que la dernière version a déjà un correctif, ou peut-être y a-t-il un argument de ligne de commande obscur pour que cela fonctionne)?
Pendant ce temps, je viens de compiler mon code avec des optimisations, et il est une douleur de débogage: -O3
Enums fortement typés? Cool! – dreamlax
Son encore "C++ 0x" .. BS dit que le "x" est hexadécimal. :) –
Allons-nous prendre des paris sur cela? ;-) –