В чем преимущество использования uint8_t
перед unsigned char
в C?
Я знаю, что почти в каждой системе uint8_t
- это просто typedef для unsigned char
, так зачем его использовать?
В чем преимущество использования uint8_t
перед unsigned char
в C?
Я знаю, что почти в каждой системе uint8_t
- это просто typedef для unsigned char
, так зачем его использовать?
Он документирует ваше намерение - вы будете хранить маленькие числа, а не символы.
Также это выглядит лучше, если вы используете другие определения типов, такие как uint16_t
или int32_t
.
unsigned char
или signed char
также документирует намерение, поскольку неукрашенный char
- это то, что показывает, что вы работаете с символами.
- person caf; 13.11.2009
unsigned
без украшений - это unsigned int
по определению?
- person Mark Ransom; 29.11.2009
unsigned char
и uint8_t
не являются отдельными типами, см., Например, ideone.com/GMV0uD
- person Mark Ransom; 04.04.2013
char
, похоже, подразумевает символ, тогда как в контексте строки UTF8 это может быть всего лишь один байт многобайтового символа. Использование uint8_t может прояснить, что не следует ожидать символа в каждой позиции - другими словами, каждый элемент строки / массива является произвольным целым числом, о котором не следует делать никаких семантических предположений. Конечно, все программисты на C знают это, но это может подтолкнуть начинающих задавать правильные вопросы.
- person tne; 16.01.2014
unsigned char
на самом деле не используется в первую очередь для хранения символов, поэтому проблема намерений является спорной.
- person user541686; 22.07.2014
char
является сокращением символа, довольно однозначно), но действительно не на практике < / i>, потому что это был исторически единственный стандартный 8-битный тип данных до появления C99 inttypes.h
. Теперь, когда у нас есть inttypes.h
, я чувствую, что на самом деле все дело в намерении при сравнении исходных типов данных и новых (u)int_(least/fast)N_t
типов данных, а также в намерении и гарантии того, что код либо компилируется с точной шириной, либо не компилируется вообще, когда дело доходит до (u)intN_t
.
- person tne; 27.11.2017
Чтобы быть педантичным, некоторые системы могут не иметь 8-битного типа. Согласно Википедии:
Требуется реализация для определения целочисленных типов точной ширины для N = 8, 16, 32 или 64 тогда и только тогда, когда он имеет какой-либо тип, отвечающий требованиям. Нет необходимости определять их для любого другого N, даже если он поддерживает соответствующие типы.
Таким образом, существование uint8_t
не гарантируется, хотя это будет для всех платформ, где 8 бит = 1 байт. Некоторые встроенные платформы могут отличаться, но это случается очень редко. Некоторые системы могут определять char
типы как 16-битные, и в этом случае, вероятно, не будет никакого 8-битного типа.
Помимо этой (незначительной) проблемы, лучше всего подходит ответ @Mark Ransom мое мнение. Используйте тот, который наиболее четко показывает, для чего вы используете данные.
Кроме того, я предполагаю, что вы имели в виду uint8_t
(стандартный typedef из C99, указанный в заголовке stdint.h
), а не uint_8
(не являющийся частью какого-либо стандарта).
CHAR_BIT > 8
становятся менее редкими, не более.
- person caf; 13.11.2009
uint8_t
(или typedef это к тому). Это связано с тем, что у 8-битного типа в представлении хранилища будут неиспользуемые биты, которых uint8_t
не должно быть.
- person Steve Jessop; 13.11.2009
typedef unsigned integer type uint8_t; // optional
Таким образом, по сути, стандартная соответствующая библиотека C ++ не нужна для определения uint8_t вообще (см. Комментарий // необязательно)
- person nightlytrails; 23.02.2013
uint_least8_t
для правильного указания намерения и того факта, что тип не может на самом деле быть 8-битными.
- person Toby; 29.05.2015
Все дело в написании кода, не зависящего от реализации. unsigned char
не может быть 8-битным типом. uint8_t
есть (при наличии).
sizeof(unsigned char)
вернет 1
для 1 байта. но если системный char и int имеют одинаковый размер, например, 16 бит, тогда sizeof(int)
также вернет 1
- person Toby; 29.05.2015
#if CHAR_BIT == 8
или #ifdef UINT8_MAX
- person chux - Reinstate Monica; 28.02.2018
uint8_t
гарантированно относится к 8-битному типу. Не гарантируется, что этот тип доступен. Но если он есть, то шириной ровно 8 бит. Верно, что char
не гарантированно будет иметь 8-битную ширину, но uint8_t
не имеет ничего общего с char
.
- person AnT; 18.03.2020
Как вы сказали, «почти в каждой системе».
char
, вероятно, изменится с меньшей вероятностью, но как только вы начнете использовать uint16_t
и друзей, использование uint8_t
смешивается лучше и может даже стать частью стандарта кодирования.
По моему опыту, есть два места, где мы хотим использовать uint8_t для обозначения 8 бит (и uint16_t и т. Д.) И где мы можем иметь поля меньше 8 бит. В обоих случаях пространство имеет значение, и нам часто нужно смотреть на необработанный дамп данных при отладке и иметь возможность быстро определить, что он представляет.
Первый - в протоколах RF, особенно в узкополосных системах. В этой среде нам может потребоваться упаковать как можно больше информации в одно сообщение. Второй - во флэш-памяти, где у нас может быть очень ограниченное пространство (например, во встроенных системах). В обоих случаях мы можем использовать упакованную структуру данных, в которой компилятор позаботится об упаковке и распаковке за нас:
#pragma pack(1)
typedef struct {
uint8_t flag1:1;
uint8_t flag2:1;
padding1 reserved:6; /* not necessary but makes this struct more readable */
uint32_t sequence_no;
uint8_t data[8];
uint32_t crc32;
} s_mypacket __attribute__((packed));
#pragma pack()
Какой метод вы используете, зависит от вашего компилятора. Вам также может потребоваться поддержка нескольких разных компиляторов с одинаковыми файлами заголовков. Это происходит во встроенных системах, где устройства и серверы могут быть совершенно разными - например, у вас может быть устройство ARM, которое взаимодействует с сервером x86 Linux.
Есть несколько предостережений при использовании упакованных структур. Самая большая проблема заключается в том, что вы должны избегать разыменования адреса участника. В системах с многобайтовыми выровненными словами это может привести к несогласованному исключению и дампу ядра.
Некоторые люди также будут беспокоиться о производительности и будут утверждать, что использование этих упакованных структур замедлит вашу систему. Верно, что за кулисами компилятор добавляет код для доступа к невыровненным элементам данных. Вы можете убедиться в этом, посмотрев код сборки в своей среде IDE.
Но поскольку упакованные структуры наиболее полезны для связи и хранения данных, данные могут быть извлечены в неупакованное представление при работе с ними в памяти. Обычно в любом случае нет необходимости работать со всем пакетом данных в памяти.
Вот несколько важных дискуссий:
работает пакет прагмы (1) и __attribute__ ((выровненный (1))) а>
Является ли __attribute __ ((упаковано)) / #pragma pack небезопасным для gcc?
http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html
Немногое. С точки зрения переносимости char
не может быть меньше 8 бит, и ничто не может быть меньше char
, поэтому, если данная реализация C имеет беззнаковый 8-битный целочисленный тип, это будет char
. В качестве альтернативы, у него может не быть его вообще, и в этом случае любые typedef
уловки станут неактуальными.
Его можно использовать для лучшего документирования вашего кода в том смысле, что ясно, что вам нужны 8-битные байты и ничего больше. Но на практике это разумное ожидание практически где угодно (есть платформы DSP, на которых это не так, но шансы на то, что ваш код там запущен, невелики, и вы можете с тем же успехом выполнить ошибку, используя статическое утверждение в верхней части вашей программы на такая платформа).
typedef struct { unsigned i :8; } uint8_t;
, но вам придется использовать его как uint8_t x; x.i = ...
, так что это будет немного громоздко.
- person Chris Lutz; 13.11.2009
unsigned char
мог хранить значения от 0 до 255. Если вы можете сделать это в 4 битах, снимаю шляпу перед вами.
- person Chris Lutz; 13.11.2009
uint8_t
к реализации. Интересно, компиляторы для DSP с 16-битными символами обычно реализуют uint8_t
или нет?
- person Steve Jessop; 13.11.2009
uint8_t
- он должен иметь его тогда и только тогда, когда он имеет соответствующий тип. Однако требуется предоставить uint8_least_t
, что составляет не менее 8 бит (но может быть больше).
- person Pavel Minaev; 13.11.2009
#include <stdint.h>
, и использовать uint8_t
. Если платформа есть, она вам ее отдаст. Если на платформе его нет, ваша программа не будет компилироваться, и причина будет ясна и очевидна.
- person Pavel Minaev; 13.11.2009
uint8_t
существует вообще, то в любом случае будет unsigned char
.
- person caf; 13.11.2009
sizeof(uint8_t) == sizeof(char)
, хотя UCHAR_MAX != 255
, но это нормально, поэтому типы не должны использовать все свои биты памяти. Под пощечиной я, конечно, подразумеваю страстный, но вежливый запрос. Они имеют право отказаться от этого, но насколько они уверены, что вы не прибегнете к насилию? ;-)
- person Steve Jessop; 13.11.2009
uint8_least_t
и применить переполнение по модулю 256 для себя. Я предполагаю, что вы можете написать это так, чтобы в любом неопределенно оптимизирующем компиляторе, где uint8_least_t
- 8 бит, все лишние операции опускались.
- person Steve Jessop; 13.11.2009
unsigned char
специально требуется для полного использования всех битов хранения как в ISO C, так и в C ++. См. 6.2.6.1/3 (и соответствующую сноску) для C99 и 3.9.1 / 1 для C ++ 03.
- person Pavel Minaev; 13.11.2009
unsigned char
(который в этом примере 16-битный) использует все биты, но AFAIK uint8_t
не обязательно. Следовательно, uint8_t
может быть меньше unsigned char
по диапазону, хотя, очевидно, не по размеру хранилища. Поэтому я не понимаю, почему разработчику компилятора должно быть трудно поддерживать uint8_t
. Это может быть чудовищно неэффективно, но это отдельная тема.
- person Steve Jessop; 13.11.2009
uint8_t
существует, тогда unsigned char
также должен быть 8-битным, это не запрещает реализации делать uint8_t
8-битным расширенным целочисленным типом. Было бы действительно полезно иметь 8-битный беззнаковый тип, который не получает специальной обработки псевдонимов, данной для unsigned char
, и ничто не запрещает реализации сделать uint8_t
таким типом [IMHO, правильный способ определения такого типа было бы дать ему специальное имя, которое могло бы иметь псевдоним uint8_t
в реализациях, поддерживающих последнее ...
- person supercat; 15.08.2016
Это действительно важно, например, когда вы пишете сетевой анализатор. заголовки пакетов определяются спецификацией протокола, а не тем, как работает компилятор C.
Почти в каждой системе я встречал uint8_t == unsigned char, но это не гарантируется стандартом C. Если вы пытаетесь написать переносимый код и важно, какой именно размер памяти, используйте uint8_t. В противном случае используйте беззнаковый символ.
uint8_t
всегда соответствует диапазону и размеру unsigned char
и заполнению (нет), когда unsigned char
8-битный. Когда unsigned char
не является 8-битным, uint8_t
не существует.
- person chux - Reinstate Monica; 04.12.2016
unsigned char
8-битный, uint8_t
гарантированно будет typedef
, а не typedef
расширенного целочисленного типа без знака?
- person hsivonen; 28.02.2018
unsigned char/signed char/char
- это наименьший тип - не менее 8 бит. unsigned char
не имеет отступов. Чтобы uint8_t
был, он должен быть 8-битным, без заполнения, существовать из-за реализации, предоставляемой целочисленным типом: соответствие минимальным требованиям unsigned char
. Что касается ... гарантированно будет typedef ... похоже, хороший вопрос для публикации.
- person chux - Reinstate Monica; 28.02.2018