Chciałbym napisać funkcję ogólną, aby wykryć, czy tablica wskaźników do jakiegoś dowolnego typu zawiera NULL
. Moją pierwszą próbą było coś wzdłuż tych linii:Pisanie funkcji ogólnej w celu wykrycia, czy tablica wskaźników zawiera 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;
}
Wskazywano, że może to doprowadzić do ścisłego naruszenie aliasingu, ponieważ tablica wskaźników do Foo
byłyby dostępne jako tablicy wskaźników do void
, którego nie ma na liście jako jeden z dozwolonych sposobów obiekt może być dostępne w C.2011 § 6,5 ¶ 7.
mógłbym przepisać na dostęp do funkcji tablicę wskaźników jak unsigned char *
zamiast, ale nie jestem pewien jak wykonać NULL
sprawdź bez łamania ścisłego aliasowania. Czy ktoś może podać prawidłową technikę?
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;
}
Celem jest, aby napisać rodzajowe funkcji, które działają tak samo jak konkretnej funkcji typu. Innymi słowy, rodzajowy wersja funkcji poniżej:
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;
}
Nie jest to ogólnie możliwe. Nie ma wymogu, że 'sizeof (void *)' jest równe 'sizeof (Foo *)'.Mogą być nierówne na maszynach adresowanych bez bajtów, gdzie 'sizeof (void *)' jest trochę większe niż 'sizeof (Foo *)' ze względu na potrzebę zapisania bajtu w słowie, do którego odwołuje się wskaźnik. –
Czy chcesz, aby kod uwzględniał tylko wskaźnik zerowy o wartości '(void *) NULL' lub chciałby obsłużyć możliwość, że platforma ma różne wartości wskaźników null? (Oczywiście wszystkie wskaźniki zerowe są sobie równe - choć mogą mieć różne kodowania). – chux
@RaymondChen: Dzięki za wniesienie tego, jest to ważny punkt. Wysłałem odpowiedź, która powinna to wyjaśnić. Jednak w przypadku takiej maszyny prawdopodobnie skończyłbym projektując ją jako 30-bitową adresowalną (dla słów 4-bajtowych) lub 61-bitową adresowalną (dla słów 8-bajtowych) zamiast próbować radzić sobie ze wskaźnikami o różnych rozmiarach. – jxh