Я хотел бы написать общую функцию, чтобы определить, содержит ли массив указателей какой-либо произвольный тип NULL
. Моя первая попытка была что-то вдоль этих линий:Написание общей функции для определения того, содержит ли массив указателей 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;
}
Было отмечено, что это может вызвать строгое нарушение сглаживания, так как массив указателей на Foo
будет доступен как массив указателей на void
, который не указано в списке в качестве одного из разрешенных способов объекта разрешается доступ в C.2011 § 6,5 ¶ 7.
Я мог бы переписать функцию, чтобы получить доступ к массиву указателей, как unsigned char *
вместо этого, но я не знаю, как выполнить NULL
проверка без нарушения строгого наложения. Может ли кто-нибудь предоставить действительную технику?
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;
}
Цель состоит в том, чтобы написать обобщенную функцию, которая будет работать так же, как специфическая функция типа. Другими словами, общая версия функции ниже:
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;
}
Это невозможно вообще. Нет требования, чтобы 'sizeof (void *)' был равен 'sizeof (Foo *)'.Они могут быть неравными на машинах, не адресуемых по байтам, где 'sizeof (void *)' немного больше, чем 'sizeof (Foo *)' из-за необходимости записи байта в слово, которое указывает указатель. –
Вы хотите, чтобы код рассматривал только нулевой указатель со значением '(void *) NULL' или хотел бы обработать возможность того, что платформа имеет различные значения нулевых указателей? (Конечно, все нулевые указатели приравниваются друг к другу, хотя могут иметь разные кодировки.) – chux
@RaymondChen: Спасибо, что принесли это, это действительная точка. Я отправил ответ, который должен учитывать это. Тем не менее, для такой машины я, вероятно, закончил бы ее создание 30-битным адресом (для 4-байтовых слов) или 61-битным адресом (для 8-байтовых слов) вместо того, чтобы пытаться обращаться с указателями разного размера. – jxh