Как выполнить переносимую 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.

Ответ 6

Если у вас есть Boost в каталоге system include, вы можете сказать

#include "boost/cstdint.hpp"
boost::int64_t my_64_bit_number;

Если он находится в каталоге include системы, предупреждения автоматически подавляются.

Ответ 7

Вы можете заменить использование long long одной из многих библиотек С++ bigint. Я уверен, что некоторые из них избегают этой ошибки компилятора. Лично я предпочитаю придерживаться ошибки.