Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 05/05/2016, à 17:22

Bigcake

[C] Mais que fait donc cette déclaration ?

Bonjour,

Je viens de découvrir un nouvelle façon de déclarer une variable (enfin...un truc) en C :

void  *(var)(int);

Évidemment, ça ressemble beaucoup à un pointeur sur fonction mais ce n'est pas le cas.
Gcc arrive à compiler sans erreur (avec -Wall -Wextra) cette déclaration, mais lors de l'utilisation de cette variable, gcc sort l'erreur :

 error: lvalue required as left operand of assignment

J'ai testé les cas suivants :

var = 15;
void   *function(int a)
{
}
var = function;
printf("=> %p\n", var);

Pour ce dernier cas, gcc sort l'erreur :

 référence indéfinie vers « var »
collect2: error: ld returned 1 exit status

Le code suivant compile avec un warning et affiche 1

printf("=> %d\n", sizeof (var));
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int

Quelqu'un saurait m'expliquer ce que je viens de déclarer ?

Dernière modification par Bigcake (Le 05/05/2016, à 20:23)


"Les gens" ne sont pas cons, ils ont été habitués à la facilité et à la désinformation. Le meilleur moyen de ne pas les aider, c'est de se moquer. Le meilleur moyen de les aider, c'est de les informer, encore et encore. La réflexion viendra. N'oubliez pas que vous aussi, vous êtes le con d'un autre.
Smartphone+GNU/Linux=Librem5

Hors ligne

#2 Le 05/05/2016, à 18:45

pires57

Re : [C] Mais que fait donc cette déclaration ?

A première vu je dirais que c'est un pointeur sur fonction


Utilisateur d'Archlinux, Ubuntu et Kali Linux
Administrateur système et réseau spécialisé Linux.
LinkedIn

Hors ligne

#3 Le 05/05/2016, à 18:53

Bigcake

Re : [C] Mais que fait donc cette déclaration ?

Ce n'est pas un pointeur sur fonction, l'assignation d'une fonction à cet variable ne compile pas.

void  (*var)(int); <= pointeur sur fonction
void  *(var)(int); <= autre chose

"Les gens" ne sont pas cons, ils ont été habitués à la facilité et à la désinformation. Le meilleur moyen de ne pas les aider, c'est de se moquer. Le meilleur moyen de les aider, c'est de les informer, encore et encore. La réflexion viendra. N'oubliez pas que vous aussi, vous êtes le con d'un autre.
Smartphone+GNU/Linux=Librem5

Hors ligne

#4 Le 05/05/2016, à 19:31

Bigcake

Re : [C] Mais que fait donc cette déclaration ?

Réponse à moi-même :

D'après moi, c'est comme un pointeur sur fonction (dont la valeur de retour est un void*), sauf qu'il manque une * pour que ce soit un pointeur.

Dans la logique ce serai une fonction mais sans contenu (j'ai essayer d'ajouter du contenu, ça compile pas), non appelable.

Dans le résultat compilé, la déclaration de cette variable n'existe pas.

J'en conclus donc qu'il s'agit d'un cas que gcc ne détecte pas comme une erreur, alors qu'il devrai....


"Les gens" ne sont pas cons, ils ont été habitués à la facilité et à la désinformation. Le meilleur moyen de ne pas les aider, c'est de se moquer. Le meilleur moyen de les aider, c'est de les informer, encore et encore. La réflexion viendra. N'oubliez pas que vous aussi, vous êtes le con d'un autre.
Smartphone+GNU/Linux=Librem5

Hors ligne

#5 Le 05/05/2016, à 23:47

grim7reaper

Re : [C] Mais que fait donc cette déclaration ?

Salut,

C’est la déclaration d’une fonction imbriquée (nested function), un extension GNU du C (du GNU C donc).

% cat foo.c 
#include <stdio.h>

int main(void)
{
    void  *(var)(int a) {
        printf("%d\n", a);
        return NULL;
    }
    printf("%p\n", var(42));
    return 0;
}
% gcc -std=gnu99 -o foo foo.c
% ./foo
42
(nil)

Comme c’est une extension GNU, il faut compiler avec l’une des valeurs suivantes pour std : gnu89, gnu90, gnu99, gnu9x, gnu11 ou gnu1x.

Hors ligne

#6 Le 06/05/2016, à 08:30

Bigcake

Re : [C] Mais que fait donc cette déclaration ?

okayyyy nikel merci pour l'explication smile

Par contre, je me demande le réel intérêt de ces fonctions imbriqués, pour une meilleure lisibilité ne faudrait-il pas mieux utiliser une fonction static qui sera surement intégré à la fonction appelante lors de l'optimisation du compilateur ?

Est-ce que ça a un intérêt d'optimisation/rapidité quelconque ? Leur intérêt réside-t'il uniquement dans l'utilisation du goto ?

Dernière modification par Bigcake (Le 06/05/2016, à 08:34)


"Les gens" ne sont pas cons, ils ont été habitués à la facilité et à la désinformation. Le meilleur moyen de ne pas les aider, c'est de se moquer. Le meilleur moyen de les aider, c'est de les informer, encore et encore. La réflexion viendra. N'oubliez pas que vous aussi, vous êtes le con d'un autre.
Smartphone+GNU/Linux=Librem5

Hors ligne

#7 Le 06/05/2016, à 08:49

grim7reaper

Re : [C] Mais que fait donc cette déclaration ?

L’intérêt c’est surtout d’avoir accès aux variables de la fonction parente je suppose (je n‘ai jamais utilisé cette extension GNU, d’ailleurs je me borne au C standard quand j’en fait, histoire de portabilité).

Hors ligne