Стандарт C гарантирует, что size_t
- это тип, который может содержать любой индекс массива. Это означает, что логически size_t
должен содержать любой тип указателя. Я читал на некоторых сайтах, которые я нашел в Googles, что это законно и/или всегда должно работать:
void *v = malloc(10);
size_t s = (size_t) v;
Итак, затем на C99 в стандарте введены типы intptr_t
и uintptr_t
, которые являются подписанными и неподписанными типами, гарантированными для хранения указателей:
uintptr_t p = (size_t) v;
В чем разница между использованием size_t
и uintptr_t
? Оба являются неподписанными, и оба должны иметь возможность удерживать любой тип указателя, поэтому они кажутся функционально идентичными. Есть ли какая-то реальная веская причина использовать uintptr_t
(или еще лучше, a void *
), а не size_t
, кроме ясности? В непрозрачной структуре, где поле будет обрабатываться только внутренними функциями, есть ли причина не делать этого?
Точно так же ptrdiff_t
был подписанным типом, способным удерживать различия указателя и, следовательно, способным удерживать большинство указателей, так как он отличается от intptr_t
?
Разве не все эти типы в основном обслуживают тривиально разные версии одной и той же функции? Если нет, то почему? Что я не могу сделать с одним из них, с которым я не могу справиться? Если да, то почему C99 добавили два языка, которые были бы лишними к языку?
Я готов игнорировать указатели на функции, поскольку они не применяются к текущей проблеме, но не стесняйтесь упоминать их, поскольку у меня есть скрытое подозрение, что они будут иметь центральное значение для "правильного" ответа.