быстрое небезопасное преобразование uint32_t в int32_t - PullRequest
0 голосов
/ 09 июня 2018

Я ищу быстрый способ конвертировать uint32_t в int32_t.Я могу предположить, что все числа меньше 2 ^ 31-1 и не нужно беспокоиться о переполнении в этой точке кода.Могу ли я предположить, что знаковый бит int32_t является самой большой цифрой uint32_t?С точки зрения кодирования могу ли я рассматривать указатель на значение uint32_t как указатель на значение int32_t: Является ли следующий код допустимым независимым от платформы кодом C и будет ли последнее утверждение истинным?(Это верно для моего Mac и с компиляторами Intel на Linux)

uint32_t ui = 3;
int32_t  *i = &ui;

(int32_t)ui == *i;

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

Если вы хотите быстро, и вы не беспокоитесь о переполнении, вам не нужно делать что-то необычное.Если вы просто напишите

i = ui;

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

i = (int32_t)ui;

, то любой здравомыслящий компилятор выдаст точно такую ​​же инструкцию присваивания и поглотит свои сомнения (т. Е. not предупреждать вас) о несоответствии типов.

Нет необходимости вообще вмешиваться в псевдонимы указателей или вложения типов - это только запутывает код и потенциально делает его менее надежным или менее эффективным.

Если вы беспокоитесь о конверсиях и таких вещах, какгде бит знака, вам действительно не нужно:

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

  • Хотя разумно не делать предположения, зависящие от машины, для всехнамерения и цели, вы можете предположить, что ваш код будет работать на компьютере с двумя дополнениями.(Они в значительной степени универсальны.)

  • Даже если бы потребовалось преобразование, оно в любом случае вряд ли было бы заметно медленнее, чем прямое назначение.

  • Записывая прямое присваивание в C (в отличие от некоторого вращения указателя), вы гарантируете, что даже если какое-то преобразование потребуется, ваш компилятор позаботится об этом.

0 голосов
/ 09 июня 2018

Нет, это не платформо-независимый код C.Стандарт C не требует определения int32_t и uint32_t.

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

Предполагая, что int32_t и uint32_t существуют:

Использование преобразования указателя для доступа кТип без знака, как если бы это был соответствующий тип со знаком, или наоборот, является допустимым.int32_t - это тип со знаком, соответствующий uint32_t.Как отмечает @rici, на практике это не просто верно, это жесткое требование.

В то же время это неоправданно сложно.На распространенных в настоящее время платформах простое прямое приведение от uint32_t до int32_t или наоборот, без каких-либо хитростей с указателями, потребует нулевых инструкций во время выполнения и выполнит в точности то, что вы уже ожидали.

...