Je voudrais écrire une fonction générique pour détecter si un tableau de pointeurs vers un type quelconque contient un NULL
. Ma première tentative a été quelque chose le long de ces lignes:Ecriture d'une fonction générique pour détecter si un tableau de pointeurs contient NULL
bool find_null (void *ptrs, size_t num_ptrs) {
void **array = ptrs;
size_t i;
for (i = 0; i < num_ptrs; ++i) {
if (array[i] == NULL) return true;
}
return false;
}
Il a été souligné que cela pourrait provoquer une violation stricte aliasing, puisque le tableau de pointeurs vers Foo
serait accessible en tant que tableau de pointeurs vers void
, qui ne figure pas comme l'un des moyens a permis un objet est autorisé à accéder à C.2011 § 6,5 ¶ 7.
je pouvais réécrire la fonction pour accéder au tableau de pointeurs comme unsigned char *
à la place, mais je ne suis pas sûr de savoir comment effectuer la NULL
vérifier sans briser stricte aliasing. Quelqu'un peut-il fournir une technique valide?
bool find_null (void *ptrs, size_t num_ptrs) {
unsigned char *array = ptrs;
void *p;
size_t i;
for (i = 0; i < num_ptrs; ++i) {
memcpy(&p, array + i * sizeof(p), sizeof(p));
if (p == NULL) return true;
/*
* Above seems to still break strict aliasing.
* What should be done instead?
*/
}
return false;
}
Le but est d'écrire une fonction générique qui fonctionnerait même en fonction de type spécifique. En d'autres termes, une version générique de la fonction ci-dessous:
bool find_null_Foo (Foo *array[], size_t num_ptrs) {
size_t i;
for (i = 0; i < num_ptrs; ++i) {
if (array[i] == NULL) return true;
}
return false;
}
Ce n'est pas possible en général. Il n'est pas nécessaire que 'sizeof (void *)' soit égal à 'sizeof (Foo *)'.Ils peuvent être inégaux sur des machines adressables sans octets, où 'sizeof (void *)' est un peu plus grand que 'sizeof (Foo *)' en raison de la nécessité d'enregistrer l'octet dans le mot référencé par le pointeur. –
Voulez-vous que le code considère uniquement un pointeur NULL avec la valeur '(void *) NULL' ou veut gérer la possibilité que la plate-forme ait plusieurs valeurs de pointeurs NULL? (Bien sûr, tous les pointeurs NULL sont équivalents les uns aux autres - bien qu'ils puissent avoir des codages différents.) – chux
@RaymondChen: Merci d'avoir soulevé cette question, c'est un point valide. J'ai posté une réponse qui devrait en tenir compte. Cependant, pour une telle machine, je finirais probablement par la concevoir comme adressable à 30 bits (pour des mots de 4 octets) ou adressable à 61 bits (pour des mots de 8 octets) au lieu d'essayer de traiter des pointeurs de différentes tailles. – jxh