Должен ли я привести size_t к ptrdiff_t?
У меня есть массив указателей malloc, который формирует хэш-таблицу. Чтобы пройти по хеш-таблице, я бы использовал арифметику указателей, например:
node_t ** tc = table;
size_t tcs = sizeof(node_t *);
for(long i = 0; i < tableSize; tc+=tcs, ++i) {
// Do some stuff with *tcs location in the table.
}
Вопрос в том, должен ли я сыграть size_t
вернулся sizeof()
в ptrdiff_t
для правильного добавления в инкрементной части for
состояние? или это вообще имеет значение для дополнения?
3 ответа
Нет необходимости ptrdiff_t
здесь, как нет разницы между указателями.
Что вы, вероятно, хотите, это:
for (node_t ** tc = table; tc < (table + tableSize); ++tc) {
...
}
Тебе нужно ptrdiff_t
для обработки отрицательных значений. size_t
обрабатывает положительные значения, такие как результат sizeof
в вашем примере, поэтому вам не нужен актерский состав.
При этом код выглядит подозрительно: компилятор C учитывает размер struct
в вашу арифметику указателя, поэтому тот факт, что вы должны добавить sizeof(node_t*)
на двойной указатель на node_t
вероятно ошибка Если вы хотите перейти к следующему указателю в массиве указателей, добавьте 1
к текущему значению этого указателя. Компилятор достаточно умен, чтобы умножить это 1
от sizeof(*ptr)
для вас, исходя из типа указателя.
Нет, тебе не нужно
Арифметика указателя выполняется в зависимости от типа указателя T *
, Добавление size_t
не повлияет на арифметику указателя, поскольку приращение выполняется с помощью sizeof(T)
,
Чтобы процитировать стандарт (проект C11):
6.5.6 Аддитивные операторы
Когда выражение с целочисленным типом добавляется или вычитается из указателя, результат имеет тип операнда указателя. Если операнд-указатель указывает на элемент объекта массива, а массив достаточно велик, результат указывает на смещение элемента от исходного элемента, так что разность индексов полученного и исходного элементов массива равна целочисленному выражению. Другими словами, если выражение P указывает на i-й элемент объекта массива, выражения (P)+N (эквивалентно, N+(P)) и (P)-N (где N имеет значение n) указывают соответственно i+n-м и i-n-м элементам массива, если они существуют. Более того, если выражение P указывает на последний элемент объекта массива, выражение (P)+1 указывает один за последним элементом объекта массива, а если выражение Q указывает на один последний элемент последнего элемента массива, выражение (Q)-1 указывает на последний элемент объекта массива. Если и операнд-указатель, и результат указывают на элементы одного и того же объекта массива или один после последнего элемента объекта массива, оценка не должна вызывать переполнение; в противном случае поведение не определено. Если результат указывает на один последний элемент массива, он не должен использоваться в качестве операнда оцениваемого унарного оператора *.
С другой стороны, кастинг size_t
в ptrdiff_t
может привести неверный код как ptrdiff_t
это подписанное время size_t
это тип без знака. Так что, если результирующее значение больше, чем что ptrdiff_t
может держать, тогда есть проблема. Короче говоря, арифметика указателей хорошо определена при добавлении любого целочисленного типа к типу указателя, и вам вообще не нужно такое приведение.