2015-10-06 2 views
-1

I ont le code suivant dans C:modification de la valeur d'adresse d'un pointeur de fonction

int addInt(int n, int m) { 
    return n + m; 
} 

int (*functionPtr)(int, int); 

functionPtr = &addInt; 

functionPtr est un pointeur de fonction et il pointe sur l'adresse spécifique de la fonction addInt. Je veux changer 1 bit de sa valeur, mais je ne peux pas comprendre comment.

Disons que functionPtr points 0xABC0 (en supposant une adresse de 16 bits) après la dernière déclaration. Je veux changer sa valeur à 0xABC1. J'ai essayé de ou de la valeur avec 0x1, mais je suppose que quelque chose ne va pas avec la conversion d'opérande:

functionPtr = &addInt | 0x00000001; // addresses are of 32 bits 

Je sais que déconner avec des pointeurs est risqué, mais je dois changer le bit de poids faible de l'adresse pour entrer dans l'état du pouce d'un MCU ARM Cortex-M4.

+0

Montrez vos tentatives. Vous avez besoin du bit ou de l'opérateur. –

+4

Que diable essayez-vous de faire ??? Finger avec des pointeurs de fonction ne vous mènera nulle part. – SergeyA

+0

@SergeyA Je dois changer le LSB du pointeur de fonction pour pouvoir entrer dans le mode Thumb (d'un MCU ARM Cortex-M4). – HBv6

Répondre

1

Pour modifier la valeur d'un pointeur via des opérations arithmétiques, vous devez le convertir en un type entier, effectuer l'opération, puis le reconvertir. C ne définit pas de comportement pour convertir un pointeur de fonction en autre chose qu'un autre pointeur de fonction, il n'y a donc pas de façon définie de le faire.

Vous pouvez néanmoins écrire ceci:

typedef int (*fptr)(int, int); 

functionPtr = (fptr)(((intptr_t) functionPtr) | 1); 

Le comportement que vous recherchez est l'un des résultats les plus plausibles, mais encore une fois, le comportement des deux moulages est non défini. Par conséquent, le comportement à attendre d'un appel de fonction via le pointeur modifié - si votre programme peut même aller aussi loin - est également indéfini. Le compilateur n'est même pas nécessaire pour accepter le code.

0

Probablement, c'est une mauvaise idée, mais si vous avez vraiment besoin de cela, ce qui suit peut faire l'affaire:

functionPtr = &addInt; 
*(int*)&functionPtr |= 1; 

Mais notez que ce n'est pas de manière portable et peut fonctionner ou pas de travail du tout votre environnement.

+0

Vous ne pouvez pas convertir un pointeur de fonction en toute sécurité vers un pointeur d'objet. Pire encore, cela n'a aucun sens pour ce que veut OP. – Olaf

+0

@Olaf Je n'ai pas dit que c'est sûr. Mais cela pourrait fonctionner quelquefois/quelque part. – Matt

+0

Oui, et je pourrais voler un jour/un jour (surtout vers la prochaine messe). C'est un comportement indéfini. Encore plus, il n'y a aucune raison de le faire ici. – Olaf

-2

Le format du pointeur de fonction dépend de l'architecture et de l'implémentation.

Par exemple, sur Itanium, function pointers point to a read only data structure contenant le pointeur global approprié pour le module auquel appartient la fonction et le pointeur de fonction réel.

+1

Ce mieux était un commentaire. – Olaf

0

Beaucoup ont mentionné que votre approche est dangereuse, mais dans certains cas, c'est un vrai problème, que j'ai rencontré plus d'une fois. Je soupçonne qu'au moment où votre code utilise l'instruction BL (branche et lien) qui ne change pas le mode du CPU au pouce, afin d'effectuer un appel d'ARM au pouce basé sur votre pointeur de fonction, ajoutez le drapeau -mthumb-interwork à gcc lors de la compilation de votre code:

Génère du code prenant en charge l'appel entre les jeux d'instructions ARM et Thumb . Sans cette option, sur les architectures antérieures à la version 5, les deux jeux d'instructions ne peuvent pas être utilisés de manière fiable dans un programme. Le par défaut est -mno-thumb-interwork, car un code légèrement plus grand est généré lorsque -mthumb-interwork est spécifié.Dans les configurations AAPCS , cette option n'a pas de sens.