Что следует использовать для переносимого кода: long long или int64_t?

У меня есть кодовая база с открытым исходным кодом, написанная как на C, так и на C ++. Я ищу целочисленный тип с гарантированной шириной не менее 64 бита, который может быть надежно скомпилирован на большинстве OS X (Intel, 64-бит) и Linux с открытым исходным кодом C и компиляторы C ++, без особых усилий со стороны конечного пользователя. Поддержка Windows и 32-битных клиентов в настоящее время не важна.

Я провел некоторое тестирование на OS X, и последний GCC, поставляемый с инструментами разработчика, не поддерживает режим C + 11 (и поэтому, похоже, не гарантирует доступность long long). Clang также не поддерживает это, хотя он поддерживает long long, если включен режим C99 после определенной версии.

Есть ли общее предложение использовать int64_t вместо long long, когда переносимость является важной целью? Использование спецификаторов формата кажется болезненным.

Могу ли я надежно преобразовать int64_t в long long (и аналогично unsigned эквивалент с uint64_t), чтобы использовать его с существующими функциями и библиотеками, которые принимают long long в качестве параметров? (И, конечно же, обратно.)

В таком настроении, если я отправлю код, который требует функциональности Clang не в GCC, собирается ли Clang заменить GCC в качестве предпочтительного компилятора в Linux? Могу ли я ожидать от этого компилятора по большей части, когда предлагаю исходный код конечным пользователям?

По сути, я хотел бы попросить совета у других разработчиков, которые использовали оба типа для переносимого кода C и C ++, у которых могут быть некоторые предложения о том, что может быть лучшим долгосрочным путем, учитывая вышеупомянутую цель. .


person Alex Reynolds    schedule 17.09.2012    source источник
comment
gcc имел long long в качестве расширения до c ++ 11, так что, пока вы не отключите gcc-расширения, вы должны быть в порядке с использованием long long на gcc (на самом деле я не думаю, что использовал / видел компилятор, который не предлагаю долго долго долго).   -  person Grizzly    schedule 18.09.2012
comment
Обратите внимание, что int64_t может иметь базовый тип long или long long среди других, что может вызвать проблемы с переносимостью, если требуется перегрузка.   -  person Mark B    schedule 18.09.2012
comment
Также подумайте о typedef, чтобы легко переходить от платформы к платформе.   -  person imallett    schedule 18.09.2012
comment
Следует учитывать, что использование перегрузок или шаблонов с int64_t может привести к выбору разных версий в разных системах. См. этот другой вопрос о int64_t vs long vs long long   -  person Bo Persson    schedule 18.09.2012


Ответы (3)


Типы long long и unsigned long long являются стандартными типами C и стандартными типами C ++, каждый из которых имеет как минимум 64 бита. Все известные мне компиляторы предоставляют эти типы, за исключением, возможно, режима -pedantic, но в этом случае int64_t или uint64_t также не будут доступны с компиляторами до C ++ 2011. На всех системах тоже доступно <stdint.h>. То есть, насколько я могу судить, не имеет большого значения, как вы пишете этот шрифт. Основная цель <stdint.h> - обеспечить наилучшее соответствие для определенного количества бит. Если вам нужна как минимум 64-разрядная версия, но вы также хотите воспользоваться преимуществами быстрой реализации такого типа, вы должны использовать int_least64_t или uint_least64_t из <stdint.h> или <cstdint> (в последнем случае имена определены в пространстве имен std).

person Dietmar Kühl    schedule 17.09.2012
comment
Я бы хотел, чтобы в стандарт был добавлен более крупный тип, например 128 или более, учитывая, что в наши дни, когда криптография широко используется, вам нужен такой тип, поэтому вам не нужно полагаться на множество библиотек. - person farmdve; 18.09.2012
comment
Я не видел предложения по такому типу (long long long?), Хотя я знаю, что многие системы действительно поддерживают 128-битные типы посредством поддержки SIMD: отправьте предложение в WG14 и / или WG21! - person Dietmar Kühl; 18.09.2012
comment
long long long не требуется; система, поддерживающая 128-битные целые числа, может определять расширенные целочисленные типы и определять int128_t и uint128_t в терминах этих типов. - person Keith Thompson; 18.09.2012
comment
если OP хочет самый быстрый тип как минимум с 64 битами, int_fast64_t и uint_fast64_t будут лучше - person phuclv; 11.03.2015

Есть ли общее предложение использовать int64_t вместо long long, когда переносимость является важной целью?

Я был бы очень удивлен, если бы компилятор предлагал int64_t, но не long long.

Если long long присутствует, он должен иметь как минимум 64 бита, поэтому преобразование из (u)int64_t в (unsigned) long long сохраняет значение.

Если вам нужен тип с точно 64 битами, используйте (u)int64_t, если вам нужно по крайней мере 64 бита, (unsigned) long long вполне подойдет, как и (u)int_least64_t.

person Daniel Fischer    schedule 17.09.2012

Используйте int64_t. int64_t означает 64 бита, и вы получите 64 бита, куда бы вы ни пошли. long long фактически настолько же зависит от реализации, насколько и long. То есть long long должно быть больше или равно long, но это может отличаться в зависимости от компилятора и платформы.

person TJ Bandrowsky    schedule 11.05.2020
comment
В стандартах есть гарантия, что long long должен быть не менее 64 бит. Он может быть длиннее, но не может быть короче. Итак, нет, это не так зависит от реализации, как long: для long правило состоит в том, что длина должна быть равна int, которая должна быть больше char. Итак, у вас может быть платформа с sizeof(long) == 2, но sizeof(long long) >= 8 должно быть истинным на каждой платформе. - person cmaster - reinstate monica; 11.05.2020
comment
Спасибо. Это хорошо знать. Но, по крайней мере, sizeof (long long) все еще зависит от платформы, и единственный способ получить согласованные 64 бита - int64_t. - person TJ Bandrowsky; 12.05.2020
comment
Да, но вопрос касался целочисленного типа, ширина которого гарантированно составляет минимум 64 бита. И это именно то, что обеспечивает long long. - person cmaster - reinstate monica; 12.05.2020
comment
OP говорил о переносимости, поэтому я бы выбрал фиксированный размер: int64_t. Там написано 64 бита, так что вам даже не нужно об этом думать. - person TJ Bandrowsky; 12.05.2020
comment
long long является переносимым как часть стандарта. А если у вас нет long long, то, скорее всего, у вас тоже не будет int64_t. - person cmaster - reinstate monica; 12.05.2020
comment
В течение многих лет MS не использовала долго и использовала собственный __int64 для получения 64 бита и даже немного для определения __int64_t. Не уверен, когда они стали длинными. - person TJ Bandrowsky; 12.05.2020