Стандарт 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уже предназначены для целочисленного типа со значением со знаком.