2009-11-03 4 views
10

На другой день, I came across эта конструкция:Насколько переносится литье -1 в неподписанный тип?

static_cast<size_type>(-1) 

в некотором примере кода C++, который, вероятно, (в зависимости от деталей, где size_type от), чтобы быть эквивалентно следующему C:

(size_t)(-1) 

Как я понимаю, он работает на основе того, что представление -1 в двухпараметрической арифметике равно 11111...1, для такого количества бит, как у вас есть, так что это быстрый способ получить максимальное значение, size_t может удержать. Тем не менее, я понимаю, что C не гарантирует, что будет использоваться двойной набор; если реализация C использует свое дополнение, это будет на 1 меньше максимального значения, и если оно использует знаковое значение, оно будет чуть более половины максимального значения.

Есть ли какая-то морщинка, которая мне не хватает, что гарантирует, что это работает правильно, независимо от того, используется ли выражение целых чисел? Различия между C и C++ (многие удивительные вещи)?

+3

Если вы хотите быть уверенным, всегда есть 'std :: numeric_limits :: max()'. – UncleBens

+0

Я думаю, что такие ситуации, почему у вас есть static_cast и reinterpret_cast на языке - static_cast может дать вам что-то предсказуемое (и, следовательно, полезно), но которое может иметь более медленную реализацию на некоторых платформах, тогда как reinterpret_cast может избавиться от каких-либо гарантий. – Kylotan

+3

Это ИМХО лучший способ получить несколько бит.Опционы с использованием '~ 0U' тоже работают (и если вы забудете добавить' U' и do '~ 0, вы можете в конечном итоге со всеми битами 0, например), но используя' -1', приведённый к типу 'unsigned' , он всегда работает независимо от типа. Поэтому вам не нужно заботиться о том, чтобы использовать 'ULL' или сначала использовать' unsigned short' - вы можете просто использовать '-1' и назначить его :) См. Также http://stackoverflow.com/questions/809227/ is-it-safe-to-use-1-to-set-all-bits-to-true –

ответ

19

Требования к беззнаковой арифметике гарантируют, что приведение -1 к неподписанному типу приведет к наибольшему числу возможных для целевого типа. C99, §6.2.5/9: «... результат, который не может быть представлен результирующим беззнаковым целочисленным типом, уменьшается по модулю по числу, которое больше, чем наибольшее значение, которое может быть представлено результирующим типом».

Это то же самое на языках C и C++ (в стандарте C++ аналогичная формулировка содержится в сноске 41 - это не нормативно, но объясняет другую формулировку).

+6

Для C++ нормативная формулировка находится на '4.7/2 ' –

+0

Спасибо, это именно то морщинка, о которой мне было интересно. – Pillsy

14

Чтобы быть на «безопасной» стороне и сделать это «право» (C++) способ, стоит посмотреть на STL: значение

std::numeric_limits<size_t>::max() 
+3

Единственным недостатком этого является то, что это значение не является постоянным выражением. Вы можете сделать 'integ_constant ', но 'integ_constant :: max()>' не работает :( –

2

Если вы хотите, чтобы получить максимум (или минимум) определенного типа переносимым способом, лучше всего использовать стандартный класс numeric_limits следующим образом.

#include <limits> 

size_type max = std::numeric_limits<size_type>::max() 
size_type min = std::numeric_limits<size_type>::min() 

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

5

«Как я понимаю, это работает на основании того, что представление -1 в двухпараметрической арифметике ...».

Нет, это не основано на этом факте. Это основано на стандартном требовании, что записанные значения, преобразованные в N-разрядный неподписанный тип, должны иметь значение без знака, которое «равно» оригиналу, подписанному по модулю 2^N.

Он должен работать таким образом, независимо от подписанного представления, используемого в реализации. В случае дополнения 2 это работает именно так, но для других представлений компилятору придется выполнить дополнительную работу, чтобы удовлетворить стандартное требование.

+0

Эх ... чтобы быть справедливым: стандарт написан так, как это точно позволяет легко реализовать на процессорах, которые выполняют арифметику дополнений 2. Это, конечно, не ** неверно **, чтобы вызвать дополнение 2. в объяснении. Языковые стандарты существуют для удовлетворения потребностей оборудования и пользователя, а не наоборот. –

+0

Я бы согласился с частью «обслуживать потребности пользователя». потребности аппаратного обеспечения?? ... № – AnT

+0

Я рассмотрел ответы раньше, когда я прочитал в них «значение« UINT_MAX », потому что в дополнении« -1 »является« бит-бит ». просто оставил его назад. r, я отвечу на этот ответ. –

Смежные вопросы