Я хочу понять ситуацию, касающуюся uint8_t против char, переносимости, битовых манипуляций, лучших практик, положения дел и т. Д. Знаете ли вы хорошее чтение по этой теме?
Я хочу сделать байтовый ввод-вывод. Но, конечно, у char есть более сложное и тонкое определение, чем uint8_t; Я полагаю, это было одной из причин введения заголовка stdint.
Однако у меня были проблемы с использованием uint8_t несколько раз. Несколько месяцев назад, однажды, потому что iostreams не определены для uint8_t. Разве нет библиотеки C ++, которая делает действительно хорошо определенный byte-IO, то есть читает и пишет uint8_t? Если нет, я предполагаю, что на это нет спроса. Зачем?
Моя последняя головная боль связана с тем, что этот код не скомпилирован:
uint8_t read(decltype(cin) & s)
{
char c;
s.get(c);
return reinterpret_cast<uint8_t>(c);
}
error: invalid cast from type 'char' to type 'uint8_t {aka unsigned char}'
Почему ошибка? Как заставить это работать?
Общий, переносимый, правильный путь туда и обратно:
char
, signed char
а также unsigned char
для ввода / вывода иunsigned char
в uint8_t
по мере необходимости.Например:
bool read_one_byte(std::istream & is, uint8_t * out)
{
unsigned char x; // a "byte" on your system
if (is.get(reinterpret_cast<char *>(&x)))
{
*out = x;
return true;
}
return false;
}
bool write_one_byte(std::ostream & os, uint8_t val)
{
unsigned char x = val;
return os.write(reinterpret_cast<char const *>(&x), 1);
}
Некоторое объяснение: Правило 1 гарантирует, что значения могут быть преобразованы в обоих направлениях между uint8_t
а также unsigned char
без потери информации. Правило 2 означает, что мы можем использовать операции ввода-вывода iostream на unsigned char
переменные, даже если они выражены в терминах char
s.
Мы могли бы также использовать is.read(reinterpret_cast<char *>(&x), 1)
вместо is.get()
для симметрии. (С помощью read
как правило, для потоковых потоков, превышающих 1, также требуется использование gcount()
по ошибке, но это не относится здесь.)
Как всегда, вы никогда не должны игнорировать возвращаемое значение операций ввода-вывода. Это всегда ошибка в вашей программе.
Несколько месяцев назад, однажды, потому что iostreams не определены для uint8_t.
uint8_t
в значительной степени просто typedef для unsigned char
, На самом деле, я сомневаюсь, что вы могли бы найти машину там, где ее нет.
uint8_t read(decltype(cin) & s)
{
char c;
s.get(c);
return reinterpret_cast<uint8_t>(c);
}
С помощью decltype(cin)
вместо std::istream
не имеет никакого преимущества, это просто потенциальный источник путаницы.
Актерский состав в return
— заявление не обязательно; преобразование char
в unsigned char
работает неявно.
Несколько месяцев назад, однажды, потому что iostreams не определены для uint8_t.
Они есть. Не для uint8_t
сам, но, скорее всего, для типа, который он на самом деле представляет. оператор >> перегружен для unsigned char
, Этот код работает:
uint8_t read(istream& s)
{
return s.get();
}
поскольку unsigned char
а также char
может псевдоним друг друга, вы также можете просто reinterpret_cast
любой указатель на char
строка в unsigned char*
и работать с этим.
Если вы хотите максимально портативный способ, посмотрите ответ Kerreks.