OVH Cloud OVH Cloud

question en une ligne ( inline )

11 réponses
Avatar
Geoffrey
bonjour,

je pensais que le mot clef "inline" ne s'utilisait uniquement que dans les
fichier en-tête.
Visiblement ce n'est pas le cas, le compilateur ( MSVC++2003 ) accepte les
fonctions "inline" dans le fichier cpp.

Ma question est : est-ce que cela a une influence sur la compilation du
code, si ces fonctions sont situées dans le .h ou le .cpp ???

Est ce que c'est "propre" de faire ca ?

tous les commentaires m'interessent, merci ;))

10 réponses

1 2
Avatar
bernard tatin
bonjour,

je pensais que le mot clef "inline" ne s'utilisait uniquement que dans les
fichier en-tête.
non

Visiblement ce n'est pas le cas, le compilateur ( MSVC++2003 ) accepte les
fonctions "inline" dans le fichier cpp.

Ma question est : est-ce que cela a une influence sur la compilation du
code, si ces fonctions sont situées dans le .h ou le .cpp ???

oui


Dans un f1.h :
int mafonction(const int x);

Dans le f1.cpp
#include "f1.h"
inline int mafonction(const int x) {
return x * x - 1;
}

dans f2.cpp
#include "f1.h"
int main() {
int total = 0;
for (int i=0; i<10; i++)
total += mafonction(i);
}

Le linker ne peut pas résoudre le symbole 'mafonction' dans f2.cpp.

'inline', ça veut dire que le code généré de la fonction est inséré à la
place de son appel. Par exemple, avec un (très) vilain assembleur, la
ligne total += mafonction(i) donnerait sans inline :

push [i]
call _mafonction
pop ebx
add [total], eax

_mafonction:
mov eax, [bp +/- ..] ;; me souvient plus
mul eax, eax
dec eax
ret

Alors qu'avec inline, on aurait
mov eax, [i]
mul eax, eax
dec eax
add [total], eax

On est passe de 8 instructions à 4 et on supprime un call.

Le linker ne peux pas résoudre le lien car on a dit au compilateur que
dans l'unité de compilation (f1.cpp) la fonction est inline, donc ne
génère pas de code.

Pour que mon exemple fonctionne, il y a deux possibilités :
1)
dans f1.h
inline int mafonction(const int x) {
return x * x - 1;
}

dans f1.cpp
virer le code de mafonction

2) si mafonction n'est utilisée que dans f2.c
virer tout dans f1.h et f1.cpp et faire :
inline int mafonction(const int x) {
return x * x - 1;
}

int main() {
int total = 0;
for (int i=0; i<10; i++)
total += mafonction(i);
}

Est ce que c'est "propre" de faire ca ?

Faut faire attention


tous les commentaires m'interessent, merci ;))




Voilà ce que je sais.

Bernard.

Avatar
Jean-Marc Bourguet
"Geoffrey" writes:

je pensais que le mot clef "inline" ne s'utilisait uniquement que
dans les fichier en-tête.


Pourquoi ? Apres la phase de pre-processing, le compilateur ignore
totalement ce qui vient ou pas des en-tetes.

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
Geoffrey
"Jean-Marc Bourguet" a écrit dans le message de news:

"Geoffrey" writes:

je pensais que le mot clef "inline" ne s'utilisait uniquement que
dans les fichier en-tête.


Pourquoi ? Apres la phase de pre-processing, le compilateur ignore
totalement ce qui vient ou pas des en-tetes.


donc finalement bien que le compilo ne dis rien sur la presence des inline,
finalement s'ils ne seraient pas la, ce serait pareil ??? L'optimisation
n'est pas faite ???

pourtant il existe une option des Visual pour que ce type d'optimisation
soit fait automatiquement, ou alors j'ai mal lu la doc ... !!??!!!


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
Geoffrey
"bernard tatin" a écrit dans le
message de news: 2e8Be.12459$
bonjour,

je pensais que le mot clef "inline" ne s'utilisait uniquement que dans
les fichier en-tête.
non

Visiblement ce n'est pas le cas, le compilateur ( MSVC++2003 ) accepte
les fonctions "inline" dans le fichier cpp.

Ma question est : est-ce que cela a une influence sur la compilation du
code, si ces fonctions sont situées dans le .h ou le .cpp ???

oui


Dans un f1.h :
int mafonction(const int x);

Dans le f1.cpp
#include "f1.h"
inline int mafonction(const int x) {
return x * x - 1;
}

dans f2.cpp
#include "f1.h"
int main() {
int total = 0;
for (int i=0; i<10; i++)
total += mafonction(i);
}

Le linker ne peut pas résoudre le symbole 'mafonction' dans f2.cpp.



Moi ce genre de code fonctionne !!! Aucune erreur de compilation ...
C'est bien pour ca que je posais la question ^^


'inline', ça veut dire que le code généré de la fonction est inséré à la
place de son appel. Par exemple, avec un (très) vilain assembleur, la
ligne total += mafonction(i) donnerait sans inline :

push [i]
call _mafonction
pop ebx
add [total], eax

_mafonction:
mov eax, [bp +/- ..] ;; me souvient plus
mul eax, eax
dec eax
ret

Alors qu'avec inline, on aurait
mov eax, [i]
mul eax, eax
dec eax
add [total], eax

On est passe de 8 instructions à 4 et on supprime un call.

Le linker ne peux pas résoudre le lien car on a dit au compilateur que
dans l'unité de compilation (f1.cpp) la fonction est inline, donc ne
génère pas de code.

Pour que mon exemple fonctionne, il y a deux possibilités :
1)
dans f1.h
inline int mafonction(const int x) {
return x * x - 1;
}

dans f1.cpp
virer le code de mafonction

2) si mafonction n'est utilisée que dans f2.c
virer tout dans f1.h et f1.cpp et faire :
inline int mafonction(const int x) {
return x * x - 1;
}

int main() {
int total = 0;
for (int i=0; i<10; i++)
total += mafonction(i);
}

Est ce que c'est "propre" de faire ca ?

Faut faire attention


tous les commentaires m'interessent, merci ;))


Voilà ce que je sais.

Bernard.



Avatar
Jean-Marc Bourguet
"Geoffrey" writes:

"Jean-Marc Bourguet" a écrit dans le message de news:

"Geoffrey" writes:

je pensais que le mot clef "inline" ne s'utilisait uniquement que
dans les fichier en-tête.


Pourquoi ? Apres la phase de pre-processing, le
compilateur ignore totalement ce qui vient ou pas des
en-tetes.


donc finalement bien que le compilo ne dis rien sur la
presence des inline, finalement s'ils ne seraient pas la,
ce serait pareil ???


Non. Ce que je veux t'expliquer c'est que le compilateur ne
fait aucune différence entre ce qui est dans des entêtes ou
des fichiers inclus et ce qui est dans le fichier principal.
Tout est permis dans les deux.

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
Sylvain LAROCHE

Moi ce genre de code fonctionne !!! Aucune erreur de compilation ...
C'est bien pour ca que je posais la question ^^



Il me "semble" que dans les options de compilation, il y a une case pour lui
indiquer d'utiliser réellemnt les inline ... à moins que ce soit le fait de
compiler en debug ou pas !!!



d'ailleurs si quelqu'un sait comment obliger le malloc de VisualC++ à
renvoyer une zone remplies de 0 en mode debug ? çà m'intéresse !

Avatar
Nicolas
Moi ce genre de code fonctionne !!! Aucune erreur de compilation ...
C'est bien pour ca que je posais la question ^^




Il me "semble" que dans les options de compilation, il y a une case pour lui
indiquer d'utiliser réellemnt les inline ... à moins que ce soit le fait de
compiler en debug ou pas !!!



d'ailleurs si quelqu'un sait comment obliger le malloc de VisualC++ à
renvoyer une zone remplies de 0 en mode debug ? çà m'intéresse !



Bonjour,

Peut-être en utilisant calloc() ?


Nicolas.


Avatar
kanze
bernard tatin wrote:

je pensais que le mot clef "inline" ne s'utilisait
uniquement que dans les fichier en-tête.


non

Visiblement ce n'est pas le cas, le compilateur ( MSVC++2003
) accepte les fonctions "inline" dans le fichier cpp.

Ma question est : est-ce que cela a une influence sur la
compilation du code, si ces fonctions sont situées dans le
.h ou le .cpp ???


oui

Dans un f1.h :
int mafonction(const int x);

Dans le f1.cpp
#include "f1.h"
inline int mafonction(const int x) {
return x * x - 1;
}

dans f2.cpp
#include "f1.h"
int main() {
int total = 0;
for (int i=0; i<10; i++)
total += mafonction(i);
}

Le linker ne peut pas résoudre le symbole 'mafonction' dans
f2.cpp.


P't-êt' ben qu'oui. Si une fonction est déclarée inline à un
endroit, il faut qu'elle soit déclarée inline à chaque
utilisation. Ici, ce n'est pas le cas. Mais c'est un
comportement indéfini, et j'imagine qu'il y a bien des cas où il
fonctionne -- pour diverses raisons, beaucoup de compilateurs
ignore l'inline s'il compile sans optimisation, par exemple.

'inline', ça veut dire que le code généré de la fonction est
inséré à la place de son appel.


P't-êt' ben. La norme ne dit que c'est une « suggestion » au
compilateur que tous les endroits où la fonction est appelée
sont critiques. Ensuite, c'est au compilateur de décider.
Typiquement : si on est en mode debug, le compilateur va ignorer
le inline ; il ne génèrera du code inline que dans la contexte
de l'optimisation. Et il existe des compilateurs (pas très
courant, j'avoue), dont l'optimisateur sait mieux faire pour ce
qui doit être inline que le programmeur -- ils ignorent aussi
l'inline déclaré, pour mettre ce qu'ils trouvent bien inline.

--
James Kanze GABI Software
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
bernard tatin


P't-êt' ben qu'oui. Si une fonction est déclarée inline à un
endroit, il faut qu'elle soit déclarée inline à chaque
utilisation. Ici, ce n'est pas le cas. Mais c'est un
comportement indéfini, et j'imagine qu'il y a bien des cas où il
fonctionne -- pour diverses raisons, beaucoup de compilateurs
ignore l'inline s'il compile sans optimisation, par exemple.


Il y a quelques jours, à la suite d'un copier/coller trop rapide, j'ai

eu le problème, avec le gcc d'Apple. Ma fonction inline du .hpp a été
déplacée telle quelle dans un .cpp avec le inline toujours actif. Le
linker m'a envoyé ch...er car il ne trouvait pas le symbole. Lorsque
j'ai viré l'inline, tout s'est bien passé, compilation, édition des
liens comme exécution. Il faut dire que j'étais en -O3 -g0, i.e.
optimisation à fond les ballons et pas de debug.

Cela dit, je pense qu'en full debug et en -O0 (pas d'optimisation du
tout), je pense, mais je n'ai pas testé, que les compilateurs récents ne
font pas de l'inline, mais qu'ils font du static, d'où des problèmes à
l'édition des liens.

'inline', ça veut dire que le code généré de la fonction est
inséré à la place de son appel.



P't-êt' ben. La norme ne dit que c'est une « suggestion » au
compilateur que tous les endroits où la fonction est appelée
sont critiques. Ensuite, c'est au compilateur de décider.
Typiquement : si on est en mode debug, le compilateur va ignorer
le inline ; il ne génèrera du code inline que dans la contexte
de l'optimisation. Et il existe des compilateurs (pas très
courant, j'avoue), dont l'optimisateur sait mieux faire pour ce
qui doit être inline que le programmeur -- ils ignorent aussi
l'inline déclaré, pour mettre ce qu'ils trouvent bien inline.

On est d'accord, en particulier lorsque la fonction contient une boucle

(for, while, ...) ou lorsqu'elle demande un trop grand nombre
d'instructions, plus ou moins réglable avec les options selon les
compilateurs. J'avoue que ma démonstration s'est voulue didactique mais
qu'elle n'est pas complète.

Je ne voudrais pas énerver qui que ce soit, mais en Lisp, on retrouve le
même problème. Ce qui prouverais que le problème de la compilation du
inline n'est pas spécifique au C++.

J'étais persuadé que le compilateur remplaçait inline par static
lorsqu'il ne pouvait pas faire autrement, mais quelques tests m'ont
prouvé le contraire. Et je ne peux pas donner de règle bien définie sur
les choix du compilateur, même avec les options -O0 -g3.


--
James Kanze GABI Software
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

Bernard


PS : P't-êt' ben qu'oui, t'es donc normand?


Avatar
James Kanze
bernard tatin wrote:

[...]
Cela dit, je pense qu'en full debug et en -O0 (pas
d'optimisation du tout), je pense, mais je n'ai pas testé, que
les compilateurs récents ne font pas de l'inline, mais qu'ils
font du static, d'où des problèmes à l'édition des liens.


Je crois qu'en général, ils génèrent des symboles « weak » weak.
En quel cas, ça marche.

[...]
J'étais persuadé que le compilateur remplaçait inline par
static lorsqu'il ne pouvait pas faire autrement, mais quelques
tests m'ont prouvé le contraire. Et je ne peux pas donner de
règle bien définie sur les choix du compilateur, même avec les
options -O0 -g3.


La sémantique d'une fonction inline est exactement la même que
si elle n'était pas inline. Du coup, le remplacer par static ne
marche pas à tous les coups. Sous Solaris, au moins (et je crois
en général, au moins sous Unix), la solution a été de le générer
avec des liens « weak ». C-à-d que l'éditeur de liens l'ignore
s'il n'en a pas besoin, et le prend s'il en a.

[...]
PS : P't-êt' ben qu'oui, t'es donc normand?


Moi non, mais quand j'apprenais le français, j'avais bien une
petite amie normande. Et de quelque part, j'ai l'impression de
ne pas vouloir s'engager, c'est typiquement normand -- j'ai
souvent entendu « p't-êt' ben qu'oui, p't-êt' ben que non » des
normands, mais rarement l'équivalent des gens qui n'étaient pas
normands.

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

1 2