Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Fonction main et liaison externe

2 réponses
Avatar
candide
Bonjour,


Je lis dans Plauger, "The standard C library", page 2 :

"A library object module should contain no definition of the the
function main with external linkage."

et il continue en disant :

"A programmer is unlikely to reuse code that insists on taking control
at program startup."

Je veux bien comprendre le deuxième point. Ce que je ne comprends pas
c'est le "with external linkage" dans le premier extrait. Dois-je
comprendre que l'énoncé suivant

"A library object module may contain a definition of the the function
main with _internal_ linkage"

est acceptable ? J'aurais le droit de définir main comme ceci :

static int main(void)
{
/* bla bla */
return 0;
}

?

J'ai essayé et gcc me renvoie un warning et Harbison & Steele dit :
"All C programs must define a single _external_ function named main"
(souligné par moi).

Et si on peut faire ainsi, quel en est l'intérêt "concret"
(i.e. dans quelles circonstances a-t-on besoin de procéder ainsi) ?

Merci.

2 réponses

Avatar
Antoine Leca
En news:47dbc6a6$0$24961$, candide va escriure:
Je lis dans Plauger, "The standard C library", page 2 :

"A library object module should contain no definition of the the
function main with external linkage."

[...] je ne comprends pas le "with external linkage" dans le
premier extrait. Dois-je comprendre que l'énoncé suivant

"A library object module may contain a definition of the the function
main with _internal_ linkage"

est acceptable ?


Je pense que oui (mais je n'y mettrais pas ma main au feu).

J'aurais le droit de définir main comme ceci :

static int main(void)
{
/* bla bla */
return 0;
}



Tout seul dans une unité, notons que cela n'aurait pas beaucoup de sens.
Donc je suppose que cette fonction est accompagné d'autre code, qui
utiliserait cette fonction main() à liaison interne (par appel ou en gardant
un pointeur dans un objet statique ou alloué).

De plus, pour un environnement hébergé, tu devrais évidemment avoir dans une
_autre_ unité une définition de main avec liaison externe, de manière à
satisfaire la liaison qu'y réalise la bibliothèque système.


J'ai essayé et gcc me renvoie un warning et Harbison & Steele dit :
"All C programs must define a single _external_ function named main"
(souligné par moi).


Jusque là, tout le monde semble assez d'accord, non ?
(le "external" auquel se réfère H&B signifie le main() avec liaison
externe).


Et si on peut faire ainsi, quel en est l'intérêt "concret"
(i.e. dans quelles circonstances a-t-on besoin de procéder ainsi) ?


Le seul intérêt que je vois à ce genre de manipulation, ce pourrait être de
pouvoir tester dans une unité un fonctionnemnt particulier (par exemple un
appel récursif à main), tout en gardant le contrôle du programme dans une
autre unité, non destinée à figurer dans le programme final, où il y aurait
le main effectif.

Un autre utilité (avec le "static" devant main qui serait effaçable par
macro), ce serait pour mettre un code de test dans une unité ; avec le
static effacé, on pourrait lier l'unité avec la bibliothèque standard et
obtenir un programme de test. Cela pourrait avoir l'aspect suivant

int mafonction() { /* ... */ }
#ifndef TEST
static
#endif
int main(void) { /* code de test */ }

Cependant, on a plutôt l'habitude d'écrire

#ifndef TEST
static
int main(void) { /* code de test */ }
#endif

qui a l'avantage de produire un module plus petit.


Antoine

Avatar
candide



tu devrais évidemment avoir dans une


"évidemment" : pour moi, ça n'a rien d'évident

_autre_ unité une définition de main avec liaison externe, de manière à
satisfaire la liaison qu'y réalise la bibliothèque système.


OK, je n'ai pas compris tout de suite. Alors donc


#include <stdio.h>

static int main (void)
{
printf("bonjour !n");
return 0;
}

me donne :



0.c:4: attention : «main" is normally a non-static function
0.c:4: attention : «main" defined but not used
/usr/lib/gcc/i486-linux-gnu/4.1.3/../../../../lib/crt1.o: In function
`_start':
(.text+0x18): undefined reference to `main'
collect2: ld a retourné 1 code d'état d'exécution

Donc, il faudrait "deux" fonctions main, ça fait bizarre.



Le seul intérêt que je vois à ce genre de manipulation, ce pourrait être de
pouvoir tester dans une unité un fonctionnemnt particulier


Je n'ai trouvé qu'un seul exemple sur Google codesearch :

#if !APR_HAS_THREADS
static int main(void)
{
printf("This test requires APR thread support.n");
return 0;
}

/* code omis */

#else /* APR_HAS_THREADS */
int main(void)
{
/* code omis */

apr_terminate();
return 0;
}

#endif /* APR_HAS_THREADS */

Je me demande toujours si c'est à ce genre de chose que Plauger faisait
allusion.