Стандарт C гарантирует, что size_t
это тип, который может содержать любой индекс массива. Это означает, что, по логике, size_t
должен быть в состоянии содержать любой тип указателя. Я читал на некоторых сайтах, которые я нашел на Google, что это законно и / или должно всегда работать:
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 *
), а не a size_t
, кроме ясности? В непрозрачной структуре, где поле будет обрабатываться только внутренними функциями, есть ли причина не делать этого?
Точно так же ptrdiff_t
был подписанный тип, способный содержать различия в указателях и, следовательно, способный удерживать практически любой указатель, так чем он отличается от intptr_t
?
Разве все эти типы не обслуживают тривиально разные версии одной и той же функции? Если нет, то почему? Что я не могу сделать с одним из них, что я не могу сделать с другим? Если так, то почему C99 добавил в язык два по существу лишних типа?
Я готов не обращать внимания на указатели функций, поскольку они не относятся к текущей проблеме, но не стесняйтесь упоминать их, так как у меня есть скрытое подозрение, что они будут центральными для «правильного» ответа.
size_t
и ,uintptr_t
кроме того, что оptrdiff_t
иintptr_t
- не оба из них будет иметь возможность хранить один и тот же диапазон значений почти на любой платформе? Почему существуют целочисленные типы как со знаком, так и без знака, особенно если ониptrdiff_t
уже предназначены для целочисленного типа со значением со знаком.