Каков правильный тип для индексов массива в C?

Объекты

NSDate не имеют часовых поясов. Они представляют собой абсолютный момент времени. Однако, когда вы запрашиваете его для своего description (путем печати его с помощью NSLog(), например,), он должен выбрать часовой пояс. Самым разумным выбором по умолчанию является GMT. Если вы не находитесь в GMT, дата будет казаться неправильной, на величину вашего собственного смещения.

Вы должны всегда использовать NSDateFormatter для создания строки для отображения. Часовой пояс форматирования должен быть установлен на ваш, который по умолчанию.

36
задан Ciro Santilli 新疆改造中心996ICU六四事件 10 March 2018 в 07:09
поделиться

5 ответов

Я почти всегда использую size_t для индексов массивов/счетчиков циклов. Конечно, есть некоторые особые случаи, когда вам могут понадобиться знаковые смещения, но в целом использование знаковых типов сопряжено со многими проблемами:

Самый большой риск заключается в том, что если вам передается огромный размер/смещение от вызывающей стороны, которая рассматривает вещи как беззнаковые (или если вы читаете его из файла, которому не доверяете), вы можете интерпретировать его как отрицательное число и не понять, что оно выходит за границы. Например, if (offset запишет куда-то, куда не следует.

Другой проблемой является возможность неопределенного поведения при переполнении знаковых целых чисел. Независимо от того, используете ли вы беззнаковую или знаковую арифметику, есть проблемы с переполнением, о которых нужно знать и проверять, но лично я считаю, что с беззнаковым поведением гораздо проще справиться.

Еще одна причина использовать беззнаковую арифметику (в общем случае) - иногда я использую индексы как смещения в битовом массиве и хочу использовать %8 и /8 или %32 и /32. При использовании знаковых типов это будут фактические операции деления. В случае беззнаковых типов могут быть сгенерированы ожидаемые операции побитового деления и битового сдвига.

25
ответ дан 27 November 2019 в 01:22
поделиться

Я обычно использую size_t для смещений массива, но если Вы хотите отрицательную индексацию массива, используйте int. Это в состоянии обратиться к максимальному размерному массиву, гарантируемому C89 (32 767 байтов).

, Если Вы хотите получить доступ к массивам максимального размера, гарантируемого C99 (65 535 байтов), используйте unsigned.

Посмотрите предыдущие изменения для доступа к позволенным массивам, но не гарантируемые C.

1
ответ дан JL2210 8 August 2019 в 15:56
поделиться

Я думаю, вам следует использовать ptrdiff_t по следующим причинам

  • Индексы могут быть отрицательными. Поэтому для общего утверждения все беззнаковые типы, включая size_t , не подходят.
  • Тип p2 - p1 - ptrdiff_t .Если i == p2 - p1 , тогда вы сможете получить p2 обратно с помощью p2 == p1 + i . Обратите внимание, что * (p + i) эквивалентно p [i] .
  • В качестве еще одного указания для этого «общего типа индекса» тип индекса, который используется при разрешении перегрузки, когда встроенный оператор [] (например, для указателя) конкурирует с пользовательским оператор [] (например, вектор) - это именно то, что ( http://eel.is/c++draft/over.built#16 ): >

    Для каждого cv-квалифицируемого или cv-неквалифицированного типа объекта T существуют кандидатные операторные функции вида

     T * operator + (T *, std :: ptrdiff_t);
    T & оператор [] (T *, std :: ptrdiff_t);
    T * оператор- (T *, std :: ptrdiff_t);
    T * оператор + (std :: ptrdiff_t, T *);
    T & оператор [] (std :: ptrdiff_t, T *);
    

РЕДАКТИРОВАТЬ: если у вас есть действительно большой массив или указатель на действительно большую часть памяти, то мой "общий тип индекса" не сокращает его, поскольку тогда не гарантируется, что вы может вычесть адрес первого элемента из адреса последнего элемента. Тогда следует использовать ответ @Ciro https://stackoverflow.com/a/31090426/34509 . Лично я стараюсь избегать использования беззнаковых типов из-за их неспособности представлять отрицательные граничные случаи (например, конечные значения цикла при итерации в обратном направлении), но это своего рода религиозные дебаты (хотя я не одинок в этом лагере) . В случаях, когда требуется использование беззнакового шрифта, я, конечно же, должен отказаться от своей религии.

37
ответ дан 27 November 2019 в 01:22
поделиться

Поскольку тип sizeof (array) (и аргумент malloc ) равен size_t , и массив может не содержит больше элементов, чем его размер, из этого следует, что size_t может использоваться для индекса массива.

ИЗМЕНИТЬ Этот анализ предназначен для массивов с отсчетом от 0, что является обычным случаем. ptrdiff_t будет работать в любом случае, но немного странно, что индексная переменная имеет тип разности указателей.

13
ответ дан 27 November 2019 в 01:22
поделиться

Если вы заранее знаете максимальную длину вашего массива, вы можете использовать

  • int_fast*_t / uint_fast*_t
  • int_least*_t / uint_least*_t

Во всех остальных случаях я бы рекомендовал использовать

  • size_t

или

  • ptrdiff_t

в зависимости от того, хотите ли вы разрешить отрицательные индексы.

Использование

  • intptr_t / uintptr_t

также будет безопасным, но имеет немного другую семантику.

2
ответ дан 27 November 2019 в 01:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: