Переменные типа size_t и ptrdiff_t
Прочитав сообщения, связанные с size_t
и ptrdiff_t
, я хочу подтвердить следующее:
-
если максимальный размер массива меньше 1/2*(max number represent-able by size_t)
, я могу безопасно использовать ptrdiff_t
и проверить относительные расстояния между двумя указателями на один и тот же объект? (Поскольку я говорил о массиве, "указатели к тому же объекту" означает "указатели на один и тот же массив" ).
-
если я хочу объявить переменную, которая может представлять смещение от другого указателя, я лучше объявляю его как тип ptrdiff_t
?
-
Как вывести переменные типа size_t
и ptrdiff_t
в C и С++? Правильно ли следующее: Строка формата кросс-платформенной для переменных типа size_t?
-
is uintptr_t
- это просто другое имя для size_t
ИЛИ оно должно использоваться как отдельный тип из size_t
?
-
есть ssize_t
и intptr_t
другие имена для ptrdiff_t
ИЛИ его нужно использовать по-другому?
Я начинаю использовать gcc на Ubuntu. Я просто узнал об этих типах при использовании кого-то
else.
ADDed: Я хочу иметь возможность использовать смещения отрицательные. И любая разница в использовании uintptr_t
и intptr_t
?
Ответы
Ответ 1
1: если максимальный размер массива меньше 1/2 * (максимальное число может быть представлено size_t
), я могу безопасно использовать ptrdiff_t
и проверять относительные расстояния между двумя указателями на один и тот же объект
Это будет так, если sizeof(size_t) <= sizeof(prtdiff_t)
. Это будет иметь место в разумной реализации, но нет гарантии.
2: если я хочу объявить переменную, которая может представлять смещение от другого указателя, я лучше объявляю его как тип ptrdiff_t
?
Да, для этого предназначен тип.
3: Как вывести переменные типа size_t и ptrdiff_t в C и С++?
В C:
printf("%zu %td\n", size, ptrdiff);
В С++:
std::cout << size << ' ' << ptrdiff << '\n';
4: is uintptr_t
- это просто другое имя для size_t
ИЛИ оно должно использоваться как отдельный тип из size_t
?
Его следует рассматривать как отдельный тип. uintptr_t
- целочисленный тип, который может содержать любое значение указателя, преобразованное в целое число; он может не существовать на некоторых платформах.
5: есть ssize_t
и intptr_t
имя пыльника для ptrdiff_t
ИЛИ его нужно использовать по-другому?
ssize_t
не является стандартным типом в отношении языков C или С++; он определяется Posix как тип некоторых аргументов функции и возвращаемых значений. Лучше было бы использовать ptrdiff_t
, кроме случаев прямого взаимодействия с функциями Posix.
intptr_t
предназначен для хранения целочисленного представления указателя, а не разницы между указателями. На некоторых платформах они могут иметь разные размеры, а intptr_t
может вообще не определяться, поэтому их нельзя использовать взаимозаменяемо.
Я хочу иметь возможность использовать отрицательные смещения. И любая разница в использовании uintptr_t
и intptr_t
?
Не используйте ни один из этих типов для представления смещений; используйте ptrdiff_t
. Используйте эти типы в особых обстоятельствах, когда вы хотите по какой-либо причине конвертировать указатели в их целые представления.
Ответ 2
uintptr_t
и intptr_t
достаточно велики, чтобы удерживать любое значение указателя void*
без потери информации. Они должны иметь возможность однозначно представлять адрес любого объекта в вашем программном адресном пространстве - включая любой байт внутри любого объекта.
size_t
- тип, предоставляемый оператором sizeof
; ptrdiff_t
- это тип, полученный путем вычитания двух указателей. Они должны быть достаточно большими для одного объекта. (И возможно иметь такой большой объект, что вычитание двух указателей, указывающих на противоположные концы, будет переполняться.)
Большинство современных систем имеют одно монолитное адресное пространство, но C предназначен для работы с системами, которые этого не делают. Например, в некоторых системах наибольший возможный объект может представлять собой небольшую часть размера всего адресного пространства, а сравнение или вычитание указателей на отдельные объекты может быть бессмысленным. (Подумайте о сегментированной схеме адресации, где вычитание указателя и сравнение учитывают только смещение части адреса.)
Ответ 3
Предполагая, что _ptrdiff_t_
является опечаткой:
1) Да. Если максимальный размер массива меньше SIZE_MAX/2
, вы можете безопасно использовать ptrdiff_t
2) Иногда: ptrdiff_t
обычно является различием между двумя указателями, тогда как size_t
является смещением. Важное значение здесь size_t
всегда положительно, ptrdiff_t
может быть отрицательным. Обратите внимание, что на некоторых платформах они могут быть совершенно разных размеров.
3) Вы выводите переменные типа size_t
и ptrdiff_t
так же, как вы выводите любой другой тип переменной.
size_t a = 10;
ptrdiff_t b = 20;
printf("%u %d", ((unsigned int)a), ((int)b));
std::cout << a << b;
4) uintptr_t
представляет собой целое число без знака, по крайней мере такое же большое, как int*
, чтобы безопасно разрешить целочисленную математику по указателям. size_t
не может быть таким же, насколько я могу судить.
5) ssize_t
- нестандартный тип C, соответствующий ptrdiff_t
. Вместо этого используйте ptrdiff_t
. (On platforms supporting the POSIX 1003.1-1996 API standard, which includes most Unix-like systems, a signed variant of size_t named ssize_t is available, which was not part of the ANSI or ISO C standards.
http://en.wikipedia.org/wiki/Size_t)