Почему все используют стандартные типы C?

103

Если вы хотите использовать Qt , вы должны принять quint8, quint16и так далее.

Если вы хотите использовать GLib , вы должны приветствовать guint8, guint16и так далее.

В Linux есть u32, s16и так далее.

УНЦ / OS определяет SINT32, UINT16и так далее.

И если вам нужно использовать какую-то комбинацию этих вещей, вам лучше быть готовым к неприятностям. Потому что на вашей машине u32будет typedefd над longи quint32будет typedefd над intи компилятор будет жаловаться .

Почему все это делают, если есть <stdint.h>? Это какая-то традиция для библиотек?

Амомум
источник
8
@Mehrdad в программировании микроконтроллеров может иметь что угодно. Например, на AVR Mega (и, следовательно, на знаменитой Arduino) int 16 бит. Это может быть неприятный сюрприз. На мой взгляд, «unsigned short» требует больше усилий при вводе текста. И мне всегда было грустно использовать 'unsigned char' для октета <s> byte </s>. Беззнаковый символ, правда?
Amomum
2
@Mehrdad Дело в том, что ты не можешь быть уверен. Именно поэтому stdint.hбыло изобретено.
glglgl
1
@glglgl: Вот еще один способ взглянуть на проблему: вы задаете не тот вопрос? Если вы ориентируетесь на несколько систем, зачем вообще произвольно жестко закодировать количество бит в коде? т.е. почему бы просто не сказать sizeof(int) * CHAR_BIT(например) и не использовать это? Если ваш intслишком мал, чтобы представлять ваш диапазон (например, индекс массива), то вам почти наверняка не следует использовать в intлюбом случае, но что-то вроде size_t. В int32чем смысл большего? Единственная фиксированная ширина имеет смысл для связи между системами (например, файловый / сетевой формат) ...
user541686
1
@Mehrdad Нет. Иногда у меня есть значения (например, от АЦП или чего-то еще), которые мне нужно сохранить. Я знаю, что они 16-битные. Так что лучше всего использовать оттенок uint16_t(или, может быть, его fastили leastвариант). Я хочу сказать, что эти типы удобны в использовании и имеют свою причину существования.
glglgl
1
@Mehrdad: Я бы посоветовал - если кажется, что ваши усилия по созданию качественного кода стоят ваших усилий - вы должны определить свои собственные функциональные определения типов, означающие способ взаимодействия с моим API / остальной частью моего кода , и определить их по техническим причинам с точки зрения «Технические» определения типов, такие как size_tи / или uint64_t.
PJTraill 01

Ответы:

80

stdint.hне существовало, когда эти библиотеки разрабатывались. Таким образом, каждая библиотека создала свой собственный typedefфайл s.

Эдвард Карак
источник
4
И ладно, я полагаю, что отсутствие stdint.h - веская причина, но почему даже сегодня эти typedef используются над типами int, long и так далее, а не над типами stdint? Это сделало бы их, по крайней мере, взаимозаменяемыми
Amomum
25
@Amomum "Почему Glib (который был разработан для Linux) не использовал определения типов Linux?" Хотя «домашней базой» glib, безусловно, является Linux, он, безусловно, является портативной библиотекой. Определение собственных типов обеспечивает переносимость: нужно всего лишь адаптировать крошечный заголовок, который соответствует типам библиотеки, для соответствующих типов целевой платформы.
Питер - Восстановить Монику
3
@Amomum Почему Glib (который был разработан для Linux) ... Нет, это не так. Glib был создан путем до ядра Linux.
andy256
5
@ andy256 «GLib» - это не сокращение от «glibc». Это библиотека, которая является ответвлением от gtk. Не старше линукса.
2
@ andy256: glib - 1998, linux - 1991. IOW, GLib был создан после Linux.
MSalters
40

Для более старых библиотек это необходимо, потому что рассматриваемый заголовок ( stdint.h) не существует.

Однако по-прежнему существует проблема: эти типы ( uint64_tи другие) являются необязательной функцией в стандарте. Таким образом, соответствующая реализация может не поставляться с ними - и, таким образом, вынудить библиотеки по-прежнему включать их в настоящее время.

Ven
источник
14
Эти uintN_tтипы не являются обязательными, но uint_leastN_tи uint_fastN_tтипы не являются.
Кусалананда
7
@ Кусалананда: К сожалению, они имеют ограниченную полезность.
Гонки легкости на орбите,
16
Конечно, потому , что они не являются обязательными, что вы не гарантируется , что есть целое число типов с точно таким количеством битов. C по-прежнему поддерживает архитектуры с довольно странными целыми размерами.
celtschk
5
@LightnessRacesinOrbit: Как они имеют ограниченную полезность? Я должен признать, что помимо аппаратных интерфейсов, я не понимаю, почему вам нужно точное количество битов, а не просто минимум, чтобы все ваши значения соответствовали друг
другу
23
В @Amomum определения типов являются требуется , если реализация имеет тип , отвечающие требования: «Тем не менее, если реализация обеспечивает целое число типов с шириной от 8, 16, 32 или 64 бита, без заполнения бит, и (для подписанных типов) , которые имеет представление с дополнением до двух, оно должно определять соответствующие имена typedef ". (цитата из N1570, 7.20.1.1 «Целочисленные типы с точной шириной») Так что, если в стандартной библиотеке их нет, значит, сторонняя библиотека тоже не может.
Eric M Schmidt
13

stdint.h был стандартизирован с 1999 года. Более вероятно, что многие приложения определяют (фактически псевдонимы) типы, чтобы поддерживать частичную независимость от базовой машинной архитектуры.

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

Практика отражена в объектно-ориентированном фасаде. шаблон проектирования и много злоупотреблений со стороны разработчиков неизменно пишут обертку классы для всех импортируемых библиотек.

Когда компиляторы были гораздо менее стандартными, а архитектура машин могла варьироваться от 16-битных, 18-битных до 36-битных мэйнфреймов с длиной слова, это было гораздо более важным вопросом. В настоящее время эта практика гораздо менее актуальна в мире, стремящемся к использованию 32-разрядных встроенных систем ARM. Это остается проблемой для младших микроконтроллеров с нечетными картами памяти.

Пекка
источник
1
Конечно, stdint.hстандартизован с 1999 года, но как долго он доступен на практике? Люди медленно внедряют и принимают новые стандарты, и в течение этого длительного переходного периода старые методы все еще необходимы.
Siyuan Ren
1
Одна неприятная проблема stdint.hзаключается в том, что даже на платформах, где, например, longи int32_tесть тот же размер и представление, нет требования, чтобы приведение int32_t*к long*получению указателя, которое может надежно получить доступ к int32_t. Я не могу поверить, что авторы Стандарта считали очевидным, что типы, совместимые с макетом, должны быть совместимы с псевдонимами, но поскольку они не удосужились сказать об этом, авторы gcc и IIRC clang считают, что язык будет улучшен, если игнорировать псевдонимы даже в случаях, когда это очевидно.
supercat
2
@supercat - это, вероятно , стоит подавшее заявку как опечатка в комитет C ... потому что это беспричинно немой , мягко говоря
LThode
@LThode: Чтобы комитет C признал это ошибкой, он должен официально объявить поведение clang и gcc тупым. Как вы думаете, это произойдет? Лучшее, на что можно было бы надеяться (и ИМХО - логичный способ продолжения), - это определить способы, которыми программы могут указывать «режимы наложения имен». Если программа говорит, что она может принимать очень строгие правила псевдонимов, то компилятор может использовать это, чтобы разрешить оптимизацию, выходящую за рамки того, что в настоящее время возможно. Если в программе указано, что для нее требуются правила, которые несколько более
удобны для
... но по-прежнему позволял бы много полезных оптимизаций, тогда компилятор мог бы сгенерировать код, который был бы намного более эффективным, чем это было бы возможно -fno-strict-alias, но который все равно действительно работал бы. Даже если бы не существовало кодовой базы, ни один набор правил не смог бы обеспечить оптимальный баланс оптимизации и семантики для всех приложений, потому что у разных приложений разные потребности. Добавьте существующую кодовую базу, и необходимость в разных режимах станет очевидной.
supercat
3

Итак, у вас есть возможность typedef char в int.

В одном из «ужасов кодирования» упоминалось, что в заголовке одной компании есть точка, в которой программисту требуется логическое значение, а символ является логическим собственным типом для работы, и так написал typedef bool char. Позже кто-то нашел, что целое число является наиболее логичным выбором, и написал typedef bool int. Результат, задолго до появления Unicode, был фактическиtypedef char int .

Думаю, довольно много дальновидности и совместимости.

Христос Хейворд
источник