Fonction declaree sans aucun paramètre

Le
candide
Bonjour,

Soit le code suivant :

/* -- */
#include <stdio.h>

void test()
{
printf("test");
}

int main ( void )
{

test(421);

return 0;
}
/* -- */

Je n'arrive pas à savoir si ce code est valide. Quand je le compile avec les
options -W -Wall -stdÉ9 -pedantic , il ne me renvoie aucun warning. Est-ce à
dire que gcc considère la définition donnée de la fonction test() comme une
définition pré-normalisation (dite "classique") sans prototype ? Je dirais que
oui vu que la Norme dit assez laconiquement :

-
6.2.7 Compatible type and composite type
§1 ()
If only one type is a function type with a parameter type list (a function
prototype)
-


Franchement, placer une définition entre parenthèses, c'est quand même un peu
fort, non ?

Bon, si c'est ça, gcc aurait pu faire un petit effort d'avertissement.


Maintenant si la fonction admet un prototype :

-
6.7.5.3 Function declarators (including prototypes)
()
An empty list in a function declarator that is part of a definition of that
function specifies that the function has no parameters. The empty list in a
function declarator that is not part of a definition of that function specifies
that no information about the number or types of the parameters is supplied.
-



je dirais que ma liste vide fait partie de la définition de la fonction et donc
que je dois considérer que ma fonction n'admet aucun paramètre. Et donc il
s'agirait d'un UB vu que :


-
6.5.2.2 Function calls
()
If the expression that denotes the called function has a type that includes a
prototype, the number of arguments shall agree with the number of parameters.
-




Qu'en pensez-vous ?


Enfin, il me semble que si la définition

void test()
{
printf("test");
}


avait été écrite :

void test(void)
{
printf("test");
}

il n'y aurait plus aucune ambiguïté, non ?
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Kojak
Le #20029701
Le Tue, 01 Sep 2009 02:26:21 +0200,
candide a écrit :

[...]
#include
void test()
{
printf("testn");
}
[...]



Remplace "void test()" par "void test(void)", voire
"static void test(void)" si elle est locale...

Cordialement,

--
Jacques.
-ed-
Le #20030391
On 1 sep, 02:26, candide
Bonjour,

Soit le code suivant :

/* -------------------------------------- */
#include
void test()



Cette déclaration de fonction n'est pas un prototype. Elle accepte
n'importe quoi, mais le comportement reste défini (les valeurs passée
en paramètre sont simplement ignorées) ... On ne code plus comme ça
depuis 1989. Je recommande

void test(void)

qui indique clairement qu'il n'y a pas de paramètres.

Bon, si c'est ça, gcc aurait pu faire un petit effort d'avertissement.



-------------- Build: Debug in hello ---------------

Compiling: main.c
Linking console executable: binDebughello.exe
C:devhellomain.c:4: warning: function declaration isn't a prototype
Output size is 18.08 KB
Process terminated with status 0 (0 minutes, 3 seconds)
0 errors, 1 warnings

Il faut surtout prendre le temps de lire les messages ...

Enfin, il me semble que si la définition

void test()
{
     printf("test");

}

avait été écrite  :

void test(void)
{
     printf("test");

}

il n'y aurait plus aucune ambiguïté, non ?



Exactement. C'est l'objet de la modification du langage introduite en
1989 (prototypes).
candide
Le #20030721
-ed- a écrit :


Bon, si c'est ça, gcc aurait pu faire un petit effort d'avertissement.



-------------- Build: Debug in hello ---------------

Compiling: main.c
Linking console executable: binDebughello.exe
C:devhellomain.c:4: warning: function declaration isn't a prototype
Output size is 18.08 KB
Process terminated with status 0 (0 minutes, 3 seconds)
0 errors, 1 warnings

Il faut surtout prendre le temps de lire les messages ...




Tiens l'hôpital qui se moque de la charité .... c'est toi qui devrais relire les
options de compilation que j'ai passées et que j'ai pris soin de rappeler dans
mon message. Enfin, j'ai l'habitude avec toi.

Bon, je te la refais :

:~$ cat test.c
#include
void test()
{
printf("testn");/* j'ai ajouté un saut de ligne */
}

int main ( void )
{

test(421);

return 0;
}

:~$ gcc -W -Wall -stdÉ9 -pedantic -o x test.c
:~$ ./x
test
:~$

Donc, comme j'ai dit, AUCUN warning.


Pour avoir ton warning ou équivalent, il faut d'autres options :

:~$ gcc -W -Wall -stdÉ9 -pedantic -Wmissing-prototypes
-o x test.c
test.c:4: attention : no previous prototype for «test»
:~$ gcc -W -Wall -stdÉ9 -pedantic
-Wold-style-definition -o x test.c
test.c: Dans la fonction «test» :
test.c:4: attention : old-style function definition
:~$ gcc -W -Wall -stdÉ9 -pedantic -Wstrict-prototypes
-o x test.c
test.c:4: attention : function declaration isn»t a prototype
:~$

ce que tu aurais dû préciser si tu avais voulu faire une contribution vraiment
pédagogique.
nicolas.sitbon
Le #20034111
On 1 sep, 10:49, candide
-ed- a écrit :



>> Bon, si c'est ça, gcc aurait pu faire un petit effort d'avertissemen t.

> -------------- Build: Debug in hello ---------------

> Compiling: main.c
> Linking console executable: binDebughello.exe
> C:devhellomain.c:4: warning: function declaration isn't a prototype
> Output size is 18.08 KB
> Process terminated with status 0 (0 minutes, 3 seconds)
> 0 errors, 1 warnings

> Il faut surtout prendre le temps de lire les messages ...

Tiens l'hôpital qui se moque de la charité .... c'est toi qui devrais relire les
options de compilation que j'ai passées et que j'ai pris soin de rappel er dans
mon message. Enfin, j'ai l'habitude avec toi.

Bon, je te la refais :

:~$ cat test.c
#include
void test()
{
     printf("testn");/* j'ai ajouté un saut de ligne */

}

int main ( void )
{

    test(421);

    return 0;

}

:~$ gcc -W -Wall -stdÉ9 -pedantic -o x test.c
:~$ ./x
test
:~$

Donc, comme j'ai dit, AUCUN warning.

Pour avoir ton warning ou équivalent, il faut d'autres options :

:~$ gcc -W -Wall -stdÉ9 -pedantic -Wmissing-pr ototypes
-o x test.c
test.c:4: attention : no previous prototype for «test»
:~$ gcc -W -Wall -stdÉ9 -pedantic
-Wold-style-definition  -o x test.c
test.c: Dans la fonction «test» :
test.c:4: attention : old-style function definition
:~$ gcc -W -Wall -stdÉ9 -pedantic -Wstrict-pro totypes
-o x test.c
test.c:4: attention : function declaration isn»t a prototype
:~$

ce que tu aurais dû préciser si tu avais voulu faire une contribution vraiment
pédagogique.



Une question similaire avait été posé sur développez.com,
http://www.developpez.net/forums/d596001/c-cpp/c/fonction-main/#post3528133
Cordialement.
candide
Le #20038001
nicolas.sitbon a écrit :


Une question similaire avait été posé sur développez.com,
http://www.developpez.net/forums/d596001/c-cpp/c/fonction-main/#post3528133



La discussion que tu cites traite plutôt de la validité de la déclaration int
main() laquelle ne semble en fait ne faire aucun doute puisque le texte de la
Norme C99 lui-même l'utilise dans ses exemples (même si les exemples ne sont pas
normatifs) ce qui est assez incroyable puisque cette possibilité est déclarée
par la Norme elle-même comme étant une obsolescence.
candide
Le #20037991
-ed- a écrit :


Cette déclaration de fonction n'est pas un prototype. Elle accepte
n'importe quoi, mais le comportement reste défini (les valeurs passée
en paramètre sont simplement ignorées)



C'est bien sûr ça ? Parce que la Norme dit :


6.5.2.2 Function calls
Constraints
(...)
p6 If the expression that denotes the called function has a type that does not
include a prototype, the integer promotions are performed on each argument, and
arguments that have type float are promoted to double. These are called the
default argument promotions. If the number of arguments does not equal the
number of parameters, the behavior is undefined.
candide
Le #20038501
-ed- a écrit :


Cette déclaration de fonction n'est pas un prototype. Elle accepte
n'importe quoi, mais le comportement reste défini



Non, il semble se confirmer que le comportement est indéterminé, cf. la réponse
donnée sur clc où j'ai posé la question :

http://groups.google.fr/group/comp.lang.c/browse_frm/thread/98a5435ff01cf4a2?hl=fr#
Antoine Leca
Le #20059011
Le 01/09/2009 8:17, emmanuel.delahaye écrivit :
void test()



Cette déclaration de fonction n'est pas un prototype. Elle accepte
n'importe quoi, mais le comportement reste défini (les valeurs passée
en paramètre sont simplement ignorées)



Pas exactement. D'abord cela oblige les paramètres à être étendus (en
particulier les float en double, comme pour les varargs); ensuite le
comportement est indéfini lorsque les paramètres ne concordent pas en
nombre et qualité avec les arguments.


Antoine
Publicité
Poster une réponse
Anonyme