Как выполнить переносимую 64-битную арифметику, без предупреждений компилятора
Я иногда использую 64-битную арифметику в открытой исходной С++-библиотеке. Я обнаружил, что long long
отлично выполняет мою задачу. Даже около 10-летней камеры Solaris можно было скомпилировать ее. И он работает, не запускаясь С#defines в Windows.
Теперь проблема заключается в том, что я получаю жалобы от своих пользователей, потому что они компилируются с помощью GCC -патентных настроек, и GCC настаивает на выдаче предупреждений, что long long
не является частью стандарта С++. Вероятно, это правильно, но я не слишком заинтересован в стандарте С++ как таковой, я просто хочу, чтобы мой код работал с таким количеством компиляторов, насколько это возможно.
Итак, мой вопрос двоякий:
- Кто-нибудь может назвать фактические компиляторы С++, которые не поддерживают 64-битные длинные версии?
- Есть ли способ сделать GCC компилировать 64-битную арифметику (на 32-битной платформе) без предупреждений компилятора? (stdint.h не помогает, так как он также зависит от
long long
)
P.S.
Если есть платформы, где длинные longs становятся 128 бит или больше, это интересно, но не проблема для меня.
Ответы
Ответ 1
Когда ваша библиотека предоставляется в качестве источника, одним из вариантов является предоставление заголовка "портирования", в котором ответственность ваших пользователей за предоставление 64-битного типа (вы должны указать имя). Тогда также естественно, что они несут ответственность за любые предупреждения компилятора о том, что их выбор типа провоцирует, либо избегает их, либо подавляет их, либо игнорирует их.
Я предполагаю, что это то, что вы называете "возиться С#defines", но я не думаю, что с ним слишком много ошибок. Вы можете предоставить версию по умолчанию, которая просто использует long long
напрямую и будет работать на вашем 10-летнем поле Solaris, а также в Windows, поэтому большинству пользователей никогда не придется приближаться к настраиваемой пользователем части вашей библиотеки.
Затем для педантичных пользователей вы можете предоставить версию для GCC, которая включает <sys/types.h>
и использует int64_t
вместо long long
. Это не вызывает для меня предупреждения g++ -pedantic
. Вы даже можете сделать это в версии по умолчанию, узнав GCC, который, безусловно, возится С#defines, но опять же не так, как обычно для многоплатформенного продукта.
Если ваша библиотека также предоставляется как двоичные файлы для определенных платформ, то, конечно, вы должны решить, какой будет тип 64-битного типа. Если он также появляется в интерфейсе библиотеки (и, следовательно, в файле заголовка), вам просто нужно выбрать тот, который не будет вызывать предупреждения с разумными параметрами компилятора. Я думаю, что -pedantic
- разумный вариант компилятора, и, видимо, так делают ваши пользователи, поэтому снова int64_t
на GCC.
Ответ 2
В GCC используйте параметр -Wno-long-long
для компилятора, чтобы пресечь это конкретное предупреждение.
Вы также можете использовать -std=C++0x
, но, вероятно, уменьшите переносимость.
Ответ 3
Вы можете отключить предупреждение с помощью -Wno-long-long
(убедитесь, что оно появилось после -pedantic
). Для C99 требуются 64-битные целые числа, и я думаю, что также С++ 0x, поэтому компиляторы, которые их не имеют, в настоящее время становятся редкими.
Ответ 4
Вы также можете подавить предупреждение с помощью gcc " __extension__
", например:
// No '-pedantic' warning/error.
__extension__ long long foo = 2;
// Exhibits '-pedantic' warning/error.
long long bar = 3
и компиляция:
$ g++ -pedantic -fsyntax-only foo.cpp
foo.cpp:5: error: ISO C++ 1998 does not support 'long long'
Обратите внимание, что только последнее использование long long
вызвало ошибку -pedantic
, так как не было добавлено __extension__
. Несмотря на это, я бы предложил @Steve Jessop использовать int64_t
.
Ответ 5
Если вы не можете управлять переключателями, переданными в gcc, вы можете отключить предупреждение с помощью #pragma
.
http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
Ответ 6
Если у вас есть Boost в каталоге system include, вы можете сказать
#include "boost/cstdint.hpp"
boost::int64_t my_64_bit_number;
Если он находится в каталоге include системы, предупреждения автоматически подавляются.
Ответ 7
Вы можете заменить использование long long
одной из многих библиотек С++ bigint
. Я уверен, что некоторые из них избегают этой ошибки компилятора. Лично я предпочитаю придерживаться ошибки.