Как определить кодировку целых чисел со знаком в C?

Стандарт ISO C допускает три метода кодирования целых чисел со знаком: дополнение до двух, дополнение до единицы и знак/величина.

Какой эффективный или хороший способ определить кодировку во время выполнения (или в другое время, если есть лучшее решение)? Я хочу знать это, чтобы оптимизировать библиотеку bignum для различных возможностей.

Я планирую вычислять это и сохранять в переменной каждый раз, когда программа запускается, поэтому она не должна быть ослепительно быстрой - я предполагаю, что кодировка не изменится во время выполнения программы :-)


person paxdiablo    schedule 29.09.2010    source источник
comment
Вам никогда не придется делать это во время выполнения - это чисто проблема времени компиляции при компиляции для конкретной архитектуры.   -  person Paul R    schedule 29.09.2010
comment
Для библиотек bignum вам почти всегда нужны беззнаковые типы. Хотя вы можете использовать тип со знаком для слова высшего порядка, возможно, проще просто сохранить отдельный бит знака и всегда работать с положительными числами, а затем изменить смысл сложения/вычитания в зависимости от бита знака. В основном ваше собственное представление знака/величины.   -  person R.. GitHub STOP HELPING ICE    schedule 29.09.2010


Ответы (5)


Вам просто нужно проверить младшие биты константы -1 чем-то вроде -1 & 3. Это оценивается как

  1. для знака и величины,
  2. для дополнения и
  3. для двух дополнений.

Это даже должно быть возможно сделать в выражении препроцессора внутри #if #else конструкций.

person Jens Gustedt    schedule 29.09.2010
comment
@Ответ Йенса Густедта Очень красиво! Но при кросс-компиляции что именно здесь проверяется, кодировка компилятора (препроцессора) или целевой машины? - person user2596047; 18.07.2013
comment
@user2596047 user2596047, компилятор всегда должен оценивать все выражения так, как если бы они оценивались во время выполнения, чтобы выполнение кода генерации вело себя так же, как в так называемом абстрактном автомате состояний. Так что да, даже для кросс-компиляции это должно быть сделано в арифметике целевой машины, а не хост-машины. - person Jens Gustedt; 18.07.2013

Обнаружение дополнения должно быть довольно простым — что-то вроде if (-x == ~x). Обнаружение дополнения до двух должно быть примерно таким же простым: if (-x == ~x + 1). Если это ни то, ни другое, то это должен быть знак/величина.

person Jerry Coffin    schedule 29.09.2010
comment
Это тоже константные выражения, так что вы можете использовать их в #if тестах: #define TWOSCOMPLEMENT (~-1 == 0), затем #if TWOSCOMPLEMENT. - person caf; 29.09.2010
comment
ваши выражения не обязательно верны для всех случаев x, поэтому вы должны быть осторожны с пограничными случаями. В частности, это неприятный случай для дополнения до двух, когда -x провоцирует неопределенное поведение, а именно -INT_MIN может быть за пределами допустимого. - person Jens Gustedt; 29.09.2010

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

person Matthew Flaschen    schedule 29.09.2010

Получите указатель на int, который будет отображать характерный битовый шаблон. Приведите его как указатель на unsigned int, а затем проверьте битовые значения.

Выполнение этого с парой тщательно выбранных значений должно делать то, что вы хотите.

person Andrew Cooper    schedule 29.09.2010

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

Но хм... целые числа без знака не должны иметь знака, не так ли?

person Arc    schedule 29.09.2010
comment
Да... кажется, я думал слишком сложно... Джерри прав насчет использования битовых операций для проверки. Не берите в голову. Оставив это здесь как альтернативный ответ. - person Arc; 29.09.2010
comment
Да, извините, это надо было подписать. - person paxdiablo; 29.09.2010