OVH Cloud OVH Cloud

Constante dans un .h

16 réponses
Avatar
Guillaume GOURDIN
Bonjour à tous,

quelle serait, selon vous, la meilleure stratégie pour définir une
constante dans un .h, afin qu'elle soit accessible à l'exterieur.

J'en voie 2 :

- le #define (#define CONSTANTE 10), je n'aime pas, rien ne me garantie
que ce #define ne sera pas écrasé par la suite.

- la fonction (int GetConstante()), je ne suis pas fan non plus. Même si
cette méthode semble plus sûre, je ne garantie plus la constance de la
constante. Par exemple, rien n'interdit l'utilisateur d'écrire:
int constante = GetConstante();
constante += 2;

Il y a éventuellement une troisième voie que je ne maitrise pas trop, en
utilisant 'extern'.

Merci de vos éclaircissements!

6 réponses

1 2
Avatar
James Kanze
Fabien LE LEZ wrote:
On Wed, 24 Jan 2007 18:47:38 +0100, Guillaume GOURDIN :

Il me semble avoir essayé et avoir eu des problemes a
l"édition de liens...


Et avec ceci ?
static int const constante= 10;


Formellement, c'est pareil au même. Les variables static (c-à-d
définies avec le mot clé static) à la portée d'un espace
référentiel ont un linkage interne. On pourrait néaumoins
préférer l'utilisation du static pour des raisons de lisibilité.
(« Say what you mean, and mean what you say. » Que je ne vais
pas essayer de traduire en français.) De toute façon, toute
declaration de variable avec une initialisation est une
définition (même si on la déclare extern).

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
James Kanze
Guillaume GOURDIN wrote:
Après quelques tests, il semble que le 'static' ne soit pas nécessa ire,
et que Sylvain avait vu juste : 'const int constante = 10;' fonctionn e.

Merci d'avoir répondu si vite!


J'ai fait d'autres tests, et en fait si je compile avec g++, tout va
bien, mais j'ai effectivement un problème à l'édition de lien si je
compile avec gcc. Quelqu'un a t'il une explication ?


Si tu as du C++, et tu invoques l'édition de liens avec gcc, tu
vas avoir des problèmes.

En revanche, attention : la signification de :

int const constante = 10 ;

n'est pas la même en C et en C++. En C++, cette variable a un
linkage interne, c-à-d qu'elle n'existe que pour la module qui
contient la déclaration. En C, elle a un linkage externe ;
c-à-d que x réfère au même objet (ou est censé référer au m ême
objet) dans toutes les unités de compilation du programme.
C-à-d, ici, que si tu mets cette déclaration dans un en-tête C,
que tu inclus dans plusieurs unités de compilation, tu aurais
des définitions multiples. (C'est encore une raison à ajouter le
static ; comme ça, le symbole a un linkage interne et en C et
en C++.) Note cependant aussi qu'en C, avec ou sans le static,
« constante » ne peut pas faire partie d'une expression
entière constante ; quelque chose du genre :
double array[ constante ] ;
n'est pas légale (à la portée du fichier -- comme variable
locale, il marche en C, parce qu'à l'encontre de C++, le C
n'exige pas que les dimensions d'un tableau local soient des
constantes).

Autant que je sache, si le nom de ta source termine en .cc ou
.cpp, gcc le compile en C++, et s'il termine en .c, g++ le
compile en C. Ça ne doit pas donc changer quoique ce soit en ce
qui concerne le traitement de cette declaration. À mon avis, si
tu vises à ce que ton en-tête soit utilisable et en C et en C++,
c'est bien les #define dont il faut se servir ; c'est la seule
façon en C d'obtenir un nom qui vaut comme expression entière
constante. Sinon, je préfère le « static int const... », mais
la présence ou l'absence de static, ici, est une question de
style.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Jean-Marc Bourguet
"James Kanze" writes:

Autant que je sache, si le nom de ta source termine en .cc ou
.cpp, gcc le compile en C++,


Oui.

et s'il termine en .c, g++ le compile en C.


Non, en C++.


A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
James Kanze
Fabien LE LEZ wrote:
On Wed, 24 Jan 2007 20:07:14 +0100, Guillaume GOURDIN
:

J'ai fait d'autres tests, et en fait si je compile avec g++, tout va
bien, mais j'ai effectivement un problème à l'édition de lien si je
compile avec gcc. Quelqu'un a t'il une explication ?


J'avoue que j'ai du mal avec les constantes, cas particulier s'il en
est.

[Note : 1 module = 1 .cpp, avec tous les .h #inclus]

Toutefois, si tu déclares une variable en-dehors d'une fonction, elle
est automatiquement globale.


Pas forcement. Ça dépend de son type. Selon §3.5/3 de la
norme :

A name having namespace scope (3.3.5) has internal linkage
if it is the name of

-- an object, reference, function or function template that
is explicitly declared static or,

-- an object or reference that is explicitly declared const
and neither explicitly declared extern nor previously
declared to have external linkage; or

-- a data member of an anonymous union.

Note bien le deuxième point. (Ce qui ne m'est pas vraiment
clair ; considère :

typedef int const CInt ;
CInt toto = 42 ;

J'aurais tendance à dire que bien qu'ayant un type const, toto
n'est pas « explicitly declared const ». N'empèche que tous
les compilateurs que je connais donne un linkage interne à toto.
Ce qui me semble logique, et conforme à ce que j'ai toujours
compris être l'intention, même si ce n'est pas exactement ce que
le texte dit.)

En fait, je suis d'accord avec toi, et trouve que ça prête à
confusion. C'est pourquoi je conseille une utilisation
systèmatique de « extern » ou de « static » sur les
déclarations des variables à la portée d'un espace référentiel.

Et si tu déclares la même variable dans
un autre module, il y a collision au moment du link : deux variables
avec la même portée et le même nom.


Non. Si le linkage est interne (ce qui est le defaut pour des
variables const), il s'agit de deux variables distinctes, et il
n'y a pas de problème. Si le linkage est externe, il s'agit
d'une seule variable, que tu as défini deux fois : c'est une
violation de la « one definition rule ». C'est donc un
comportement indéfini : le compilateur (ou l'éditeur de liens)
peut donner une erreur, et refuser à compiler le programme, mais
il peut aussi faire n'importe quoi d'autre. (Un autre
comportement fréquent, c'est de fusionner toutes les
définitions, en choisissant une des initialisations au hazard.)

Si tu la déclares "static", par contre, sa portée est réduite au
module ; tu peux alors avoir plusieurs variables de même nom dans
plusieurs modules différents.


Je sais ce que tu veux dire, mais attention entre la distinction
entre portée et linkage. Ce ne sont pas tout à fait les mêmes
choses. La portée définit où une déclaration est visible ; le
linkage définit quand et si deux déclarations du même nom
(qualifié) réfèrent au même objet.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Dominique MICOLLET
Guillaume GOURDIN wrote:

J'ai fait d'autres tests, et en fait si je compile avec g++, tout va
bien, mais j'ai effectivement un problème à l'édition de lien si je
compile avec gcc. Quelqu'un a t'il une explication ?


Avec g++, donc en C++, une constante peut être déclarée dans plusieurs .o
différents, mais pas avec gcc, qui compile du C.

--
Cordialement

Dominique MICOLLET Email : enlever deux fr
Universite de Bourgogne
9, Avenue Alain SAVARY BP 47870 Tel : +33/(0)3-80-39-59-27
21078 DIJON CEDEX FRANCE Tfx : +33/(0)3-80-39-68-69

Avatar
James Kanze
Bruno Causse wrote:
"Sylvain" a écrit dans le message de news:
45b7d924$0$27377$

vous pouvez la déclarer N fois (une seule fois suffit):

.h

extern const int constante;

et la définir une seule et unique fois:

.cpp

const int constante = 100;


je declare mes constantes a l'interieur des classes, je n'ai aucune
variables declarés autrement(qui ne soit pas "ratachée a une classe").

est ce une bonne methode?


Dans la plupart des cas, oui. Je verrais mal, en revanche, être
obligé à écrire « Math::u03C0 » (comme en Java). Il y a
parfois des justifications pour mettre des constantes dans un
espace référentiel.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


1 2