Причины использования (или нет) stdint

Я уже знаю, что stdint используется, когда вам нужны конкретные размеры переменных для переносимости между платформами, у меня пока нет такой проблемы, но каковы минусы и плюсы ее использования, кроме уже показанного выше факта de?

глядя на него на StackOverflow и других сайтах, я нашел 2 ссылки, которые относятся к теме:

  • 1 - это говорит о портативности stdint.

  • 2 - это более конкретно о uint8_t.

тезисы две ссылки отлично подходят специально, чтобы узнать больше об основной причине этого заголовка, который является переносимостью, но для меня, что мне больше всего нравится в нем, что я думаю, что 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 (по крайней мере на ближайшие годы).