Причины использования (или нет) stdint
Я уже знаю, что stdint используется, когда вам нужны конкретные размеры переменных для переносимости между платформами, у меня пока нет такой проблемы, но каковы минусы и плюсы ее использования, кроме уже показанного выше факта de?
глядя на него на StackOverflow и других сайтах, я нашел 2 ссылки, которые относятся к теме:
тезисы две ссылки отлично подходят специально, чтобы узнать больше об основной причине этого заголовка, который является переносимостью, но для меня, что мне больше всего нравится в нем, что я думаю, что uint8_t чище, чем unsigned char (например, для хранения значения канала RBG), int32_t выглядит более значимым, чем просто int и т. д.
Итак, мой вопрос в том, что именно минусы и особенно плюсы использования stdint помимо переносимости, и должен ли я использовать его только в некоторых специфических частях моего кода или везде? если везде, как я могу использовать пользовательские функции, такие как atoi, strtok и т. д.?
спасибо!
4 ответов
плюсы
использование четко определенных типов делает код намного проще и безопаснее для порта, так как вы не получите никаких сюрпризов, когда, например, одна машина интерпретирует int
Как 16-разрядные и 32-разрядные. С stdint.h, что вы печатаете, то и получаете.
используя int
etc также затрудняет обнаружение опасных рекламных акций типа.
другое преимущество заключается в том, что с помощью int8_t
вместо char
, вы знаете, что вы всегда получаете 8-битную переменную со знаком. char
может быть подписан или без знака, это поведение, определяемое реализацией, и варьируется между компиляторами. Поэтому значение по умолчанию char
просто опасно использовать в коде, который должен быть портативным.
если вы хотите дать компилятору подсказки о том, что переменная должна быть оптимизирована, вы можете использовать uint_fastx_t
который говорит компилятору использовать максимально быстрый целочисленный тип, по крайней мере, такой же большой, как "x". В большинстве случаев это не имеет значения, компилятор достаточно умен, чтобы оптимизировать о размерах типов независимо от того, что вы ввели. Между точками последовательности компилятор может неявно изменить тип на другой, чем указан, если это не влияет на результат.
минусы
нет.
ссылка: MISRA-C:2004 правило 6.3."определения типов вместо основных типов должны использоваться обозначения размера и знака".
EDIT: удален некорректный пример.
единственная причина использовать uint8_t
, а не unsigned char
(помимо эстетических предпочтений), если вы хотите, чтобы документ, что ваша программа требует char
быть точно 8 бит. uint8_t
существует тогда и только тогда, когда CHAR_BIT==8
, согласно требованиям стандарта C.
остальное intX_t
и uintX_t
типы полезны в следующих ситуациях:
- чтение / запись диска / сети (но тогда вам также нужно использовать преобразование endian функции)
- когда вы хотите беззнаковое поведение обертки при точном отключении (но это можно сделать более переносимо с помощью
&
оператор). - когда вы контролируете точный макет структуры, потому что вам нужно убедиться, что нет заполнения (например, для
memcmp
или цели хэширования).
С другой стороны,uint_least8_t
, etc. типы полезны везде, где вы хотите избежать использования расточительно больших или медленных типов, но должны убедиться, что вы можете хранить значения определенной величины. Например, while long long
- это не менее 64 бит, это может быть 128-бит на некоторых машинах, и использовать его, когда вам нужен только тип, который может хранить 64-битные номера, было бы очень расточительно на таких машинах. int_least64_t
решает проблему.
я бы избегал использовать [u]int_fastX_t
типы полностью, так как они иногда изменить на данной машине (нарушение ABI) и поскольку определения обычно неверны. Например, для x86_64, 64-разрядный целочисленный тип считается "быстрым" для 16-, 32-и 64-разрядных значений, но в то время как сложение, вычитание и умножение имеют одинаковую скорость независимо от того, используете ли вы 32-разрядные или 64-разрядные значения, деление почти наверняка медленнее с большими, чем необходимо типами, и даже если они были одинаковой скоростью, вы используете вдвое больше памяти без пользы.
наконец, обратите внимание, что аргументы, которые некоторые ответы сделали о неэффективности использования int32_t
для счетчика, когда это не собственный целочисленный размер технически в основном правильный, но он не имеет отношения к правильному коду. Если вы не считаете небольшое количество вещей, где максимальное количество находится под вашим контролем, или какую-то внешнюю (не в памяти вашей программы) вещь, где счет может быть астрономическим, правильный тип для счета почти всегда size_t
. Вот почему все стандартные функции C используют size_t
по пунктам. Не думайте использовать что-либо еще, если у вас нет очень веской причины.
минусы
основная причина, по которой язык C не указывает размер int
или long
, etc. для вычислительной эффективности. Каждая архитектура имеет естественный, наиболее эффективный размер, и дизайнеры специально уполномочили и предназначили реализацию компилятора использовать естественные собственные данные размера данных для скорости и эффективности размера кода.
в прошлых летах, сообщение с другими машинами не было основной заботой-большинств программы были местными к машина - таким образом, предсказуемость размера каждого типа данных мало беспокоила.
настаивая на том, что определенная архитектура использует определенный размер int
считать с действительно плохая идея, хотя это, казалось бы, облегчает другие вещи.
в некотором смысле, благодаря XML и его собратьям, размер типа данных снова больше не вызывает беспокойства. Доставка машинно-специфичных двоичных структур от машины к машине снова является исключением, а не правило.
я использую типы stdint только по одной причине, когда данные, которые я храню в памяти, должны идти на диск / сеть / дескриптор в двоичной форме. Вам нужно только бороться с проблемой little-endian/big-endian, но это относительно легко преодолеть.
очевидная причина не использовать stdint, когда код не зависит от размера, в математических терминах все, что работает над рациональными целыми числами. Он будет производить уродливые дубликаты кода, если вы предоставили uint*_t
версия скажем, qsort()
для каждого расширения *
.
я использую свои собственные типы в этом случае, полученные от size_t
когда я ленив или самое большое поддерживаемое целое число без знака на платформе, когда я не.
изменить, потому что я столкнулся с этой проблемой ранее:
Я думаю, это примечательно, что по крайней мере uint8_t
, uint32_t
и uint64_t
сломаны в Solaris 2.5.1.
Поэтому для максимальной переносимости я по-прежнему предлагаю избегать stdint.h
(по крайней мере на ближайшие годы).