Pointeurs de fonctions et promotion des arguments

Une fonction ne peut pas recevoir de paramètres de type short ?

a marqué ce sujet comme résolu.

Bonjour,

En étudiant le cours je tombe sur la notion de promotion des arguments. J’avoue que j’ai un peu de mal. Il me semble que le cours dit que si je passe un argument de type short à un pointeur de fonction "générique", celui-ci sera converti en int et donc dans le corps de la fonction, on aura un int même si la fonction attendait un short.

C’est à dire que dans le code ci-dessous je m’attendais à un retour de 4 mais le retour affiche bien 2. Donc l’argument a bien été converti en short ? Mais comment, du coup ?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void foo(short a)
{
	printf("sizeof(param) : %zu\n", sizeof a);
}

int main()
{
	void (*pf) ();
	pf = &foo;

	int a = 0;
	pf(a);

	return 0;
}

retour :

sizeof(param) : 2

De plus, je ne comprends pas pourquoi mon compilateur me donne le warning suivant alors qu’il me semble bien respecter les syntaxes théoriques pour un "pointeur générique de fonction" :


warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
  pf = &foo;
     ^

+0 -0

Salut,

Comme l’indique le cours, fabriquer un pointeur générique pour une fonction qui attend un short ou un char est incorrect : comme ceux-ci seront promus en int, tu peux pas appeler de façon valide une fonction qui attend un char ou un short via un pointeur générique. Il faut que la fonction attende au minima un int (maintenant, comme le système de type de C est complètement pété, la plupart des compilos se contentent d’un warning au lieu de rejeter le code).

Par ailleurs, sizeof étant évalué au compile time, il va juste voir que foo attend un short et être évalué à la taille d’un short, donc ton code ne montre rien dans un sens ni dans l’autre.

Enfin, appeler une fonction via un pointeur générique sans lui donner le bon type est un UB, donc ton code est invalide.

Et surtout, un UB est un bug avec une machine à remonter le temps : si tu as un UB dans un chemin d’exécution, le compilo peut faire ce qu’il veut sur tout le chemin qui mène à l’UB (parce qu’il a le droit de partir du principe que les développeurs savent ce qu’ils font et donc qu’un UB ne se produit pas). C’est ce que je veux dire quand je dis que ton programme est invalide : comme le chemin d’exécution principal mène à un UB, tu n’as aucune garantie sur le comportement du programme dans son ensemble (et donc on ne peut pas raisonner dessus dans le cadre du standard C). Les UBs omniprésents dans le standard C rendent le langage difficile à utiliser correctement d’une part, et difficile à débugger d’autre part (typiquement un code avec UB peut tomber en marche dans plein de cas et tu te retrouves avec un bug qui apparaît seulement avec certaines options de compilations/versions de compilateurs/architectures).

+2 -0

Pas sûr de comprendre ce que tu veux dire. C’est pas une question de dialecte, les opérations qui sont UB ne le sont pas juste pour faire joli : c’est juste qu’intrinsèquement il y a des opérations qui sont valables syntaxiquement mais qui n’ont pas de sens (ou du moins le standard s’embête pas à lui en donner un et dit qu’un programme valide ne va pas faire ça). L’exemple typique est de déréférencer un pointeur nul.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte