Vérifier si le pointeur pointe vers un tableau donné

J’ai donc une fonction qui renvoie un pointeur sur un élément d’un tableau A. J’ai une autre fonction qui prend ce pointeur en tant que paramètre. Cependant, j’ai besoin de cette fonction pour pouvoir gérer la possibilité de lui transmettre un pointeur complètement arbitraire.

Existe-t-il un moyen de détecter si un pointeur pointe quelque part dans une structure? Dans ce cas, mon tableau A?

J’ai vu des questions similaires concernant C ++, mais pas avec C.

La seule méthode portable consiste à utiliser un test d’égalité par rapport à toutes les valeurs valides possibles pour le pointeur. Par exemple:

int A[10]; bool points_to_A(int *ptr) { for (int i = 0; i < 10; ++i) if ( ptr == &A[i] ) return true; return false; } 

Notez que l'utilisation d'un opérateur relationnel (par exemple, < ) ou d'une soustraction avec deux pointeurs constitue un comportement indéfini, à moins que les deux pointeurs pointent réellement sur des éléments du même tableau (ou d'un au-delà de la fin).

Dans la section §6.5.8 Opérateurs relationnels , la norme C11 (ISO / IEC 9899: 2011) indique:

Lorsque deux pointeurs sont comparés, le résultat dépend des emplacements relatifs dans l’espace d’adressage des objects pointés. Si deux pointeurs vers des types d’object pointent tous deux vers le même object ou tous les deux pointent après le dernier élément du même object tableau, ils se comparent égaux. Si les objects pointés sont des membres du même object agrégé, les pointeurs sur les membres de la structure déclarés ultérieurement comparent les pointeurs supérieurs aux membres déclarés précédemment dans la structure, et les pointeurs sur des éléments de tableau avec des valeurs en indice plus grandes comparent les pointeurs supérieurs aux éléments du même tableau. avec des valeurs plus faibles en indice. Tous les pointeurs vers les membres d’un même object d’union se comparent. Si l’expression P pointe sur un élément d’un object tableau et que l’expression Q pointe sur le dernier élément du même object tableau, l’expression de pointeur Q+1 compare plus grande que P Dans tous les autres cas, le comportement est indéfini.

Si vous savez que le pointeur se trouve dans la plage du tableau, les comparaisons fonctionnent. Si le pointeur est en dehors de la plage, vous ne pouvez pas être sûr que les comparaisons fonctionneront. En pratique, c’est généralement le cas, mais la norme indique explicitement que la comparaison produit un comportement indéfini.

Notez que pour un tableau SomeType array[20]; , la garantie adresse &array[20] est valide et permet une comparaison fiable avec toutes les adresses de &array[0] à &array[19] . Vous devez décider si vous voulez compter cela dans votre tableau.

Sous réserve de l’observation que la norme ne garantit pas que cela fonctionnera, vous pouvez alors comparer deux pointeurs int :

 int within_int_array(int *array, size_t num_ints, int *ptr) { return ptr >= array && ptr < array + num_ints; } 

De nos jours, vous devriez être de plus en plus prudent lorsque vous invoquez un comportement non défini. Les compilateurs font des bêtises aux programmes qui utilisent un comportement indéfini, et techniquement, vous n’avez aucun recours puisque la norme dit "comportement indéfini".