• # Oula plein de chose dans le poste

    Posté par . En réponse au message L'opérateur unaire * me laisse perplexe (pointeurs sur fonctions principalement). Évalué à 2.

    (j'ai jamais d'inspiration pour les titres des commentaires...)

    Dans ce qui précède, l'étoile s'applique en gros à ce qu'il y a à sa droite, mais, les opérateurs de cast :
    pf * tableau_pointeurs_fonctions = (pf *) malloc( sizeof(pf) * 4)
    // déclare un pointeur sur 4 pointeurs sur fonction qui retournent un int
    pourquoi est-ce que l'opérateur de cast s'écrit (pf *) ?

    Non, c'est pareil,
    malloc retourne un void, et donc le compilo gueulerait disant que tu associe un void à ton pointeur de tableau qui est de type pf. Le cast (pf)malloc dis au compilo que tu sait ce que tu fais et que le void* est comme un pf* (on appelle ça transtypage d'une variable).
    La ligne complète cumule déclaration d'une variable de type pf* et la création d'un espace mémoire de taille 4 pf

    Je sais bien que toutes ces affectations n'ont pas de sens, c'est juste pour tenter de comprendre le compilateur (gcc 4.6 en l’occurrence), et à quoi ressemble un tableau de pointeur sur fonctions qui retournent un int en mémoire ? est-ce que les argument des fonctions de ce tableau changent sa représentation ?
    J'imagine que par ailleurs c'est très dépendant de l’architecture.

    Alors la pour faire simple on va faire du pseudo assembleur, il faut comprendre comment marche un micro. Un pointeur sur fonction ce n'est jamais rien d'autre qu'une adresse mémoire ou aller exécuter du code.
    En pseudo asm on doit donc lire un adresse dans un tableau et sauter à cette adresse (si ta fonction n'as pas d'argument).
    Après le passage d'argument et la valeur de retour de la fonction sont dépendant du micro utilisé.

    Sur certaines architecture RISC on va passer les arguments dans des registres micro (et si il y a trop d'argument par un pointeur un emplacement dans la pile), le code retour de la fonction est toujours dans un registre/pseudo registre défini à l'avance (pseudo registre car si le code retour est 64bits sur un micro 16bits soit c'est un pointeur sur la valeur 64bits qui est retourné, soit la valeur est séparée sur plusieurs registres).
    Ce qui complique beaucoup les choses si on mixe du code venant de compilo différent et le rend presque impossible sans l'utilisation de thunk écris en assembleur (je vois pas le mots français pour ces routines à part glue-logique).

    Sur les architecture CISC (comme le x86) on n'as souvent que très peut de registre donc les arguments sont mis d'office dans la pile et on passe un pointeur dans un registre à la fonction. Le code retour est dans EAX (de mémoire).

    Qu'est-ce que je peux lire ou faire pour mieux comprendre ?
    Le compilo produit de l'assembleur, donc apprendre à le lire est une bonne chose pour vérifier que le résultat produit est bien celui attendu. En programmation embarqué je regarde toujours toujours l'assembleur généré.

    faire objdump -D mon_fichier.o |less

    est riche d'enseignement.