Существует ли метод подачи жалоб на стандарты для представления байта в ANSI (C89 / 90) C? Я знаю, что чаще всего char бывает байтом, но я понимаю, что это не гарантируется. Кроме того, в стандарте C99 есть stdint.h, но что использовалось до C99?
Меня интересуют как 8 бит, так и «байт» (sizeof (x) == 1).





До C99? Платформо-зависимый код.
Но почему тебя это волнует? Просто используйте stdint.h.
В каждой реализации C, которую я использовал (от старого UNIX до встроенных компиляторов, написанных инженерами по оборудованию, и до компиляторов крупных производителей) char всегда был 8-битным.
Итак, ваш совет: использовать uint8_t или использовать unsigned char?
Забавно, когда я ходил в школу, персонаж был 6-битным. Строчная стоимость 12 бит! Я так понимаю, вы не пропустите 36-битные, 60-битные и другие забавные машины, с которыми мы привыкли работать.
Вы можете найти довольно надежные макросы и определения типов в boost.
Ну, вы можете просто скопировать / вставить оттуда то, что вам нужно. Нет ничего особенного, если вам нужен только надежный тип целых чисел определенной длины.
Вы всегда можете представить байт (если вы имеете в виду 8 бит) в беззнаковом символе. Он всегда имеет размер не менее 8 бит, все биты составляют значение, поэтому в него всегда будет помещаться 8-битное значение.
Если вам нужно ровно 8 бит, я также думаю, что вам придется использовать способы, зависящие от платформы. Системы POSIX кажутся обязательный для поддержки int8_t. Это означает, что в системах POSIX char (и, следовательно, байт) всегда 8 бит.
Поддержка POSIX для stdint.h после даты C99.
о да. похоже, из 2001 года. но я думаю, что даже если у него нет компилятора c99, поставляющего его - если он на машине posix, он может воспользоваться его требованиями из stdint.h. если он в окнах ms, все мои ставки отключены :) может быть, он сможет взять что-то из cstdint.hpp boost и c'ify?
Я имею в виду байт, не обязательно 8 бит, но спасибо. Кстати, в спецификации сказано, что он должен быть не менее 8 бит, или это просто так?
да, стандартное документирование limits.h требует, чтобы UCHAR_MAX был не менее 255, не имел битов заполнения и использовал чистую двоичную систему. char должен иметь тот же диапазон и представление, что и unsigned char или signed char, но все же должен быть отдельным типом.
char всегда является байт, но не всегда октет. Байт - это наименьшая адресуемая единица памяти (в большинстве определений), октет - это 8-битная единица памяти.
То есть sizeof(char) всегда 1 для всех реализаций, но макрос CHAR_BIT в limits.h определяет размер байта для платформы, и это не всегда 8 бит. Существуют платформы с 16-битными и 32-битными байтами, поэтому char будет занимать больше бит, но это по-прежнему байт. Поскольку требуемый диапазон для char составляет от -127 до 127 (или от 0 до 255), на всех платформах он будет равен 8 битам по меньшей мере.
ISO/IEC 9899:TC3
6.5.3.4 The sizeof operator
- ...
- The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. [...]
- When applied to an operand that has type
char,unsigned char, orsigned char, (or a qualified version thereof) the result is 1. [...]
Акцент мой.
Просто для пояснений, всегда ли sizeof (char) 1 в спецификации или просто присутствует во всех реализациях?
Предполагая, что вы используете нечетную архитектуру с <8-битным байтом, не может ли char не быть байтом (поскольку CHAR_BITS> = 8)? Если нет, не могли бы вы точно определить, что вы подразумеваете под словом «байт» выше?
Требуемый диапазон для char на самом деле составляет от -127 до 127 (не забывайте, что в некоторых архитектурах используется знаковая величина или представление целого числа с дополнением) или от 0 до 255, в зависимости от того, является ли char знаковым или беззнаковым. 8-битное дополнение до двух поддерживает от -128 до 127, а не от -127 до 128.
@Chris: byte = наименьшая адресуемая единица памяти. Я не совсем понимаю, что вы имеете в виду под своим вопросом. байт меньше 8 бит означает, что платформа не может быть совместима с C.
Не понимал, что C требует> = 8-битных байтов (действительно, стандарт говорит, что байт должен содержать char, а char должен быть 8 бит). Мы достигли предела портативности C ...
Какие платформы имеют байты больше 8 бит?
@theduke, в основном DSP, например: leo.sprossenwanne.at/dsp/Entwicklungsprogramme/Entpack/CC56/ DSP /…
Байт физического оборудования меньше 8 бит не является проблемой с точки зрения соответствия C, пока логический байт, представленный реализацией C, составляет не менее 8 бит. Это означает, что машина с 7-битными аппаратными байтами может предоставить 14-битный логический байт для char и быть совместимой, но тогда все более крупные типы должны будут занимать целое (и выровненное) количество таких логических байтов (т. Е. У вас не может быть 21-битное целое число, состоящее из 3 аппаратных байтов, если вы не включили вместе с ним дополнительные 7 битов заполнения (остальная часть второго char).
В ANSI C89 / ISO C90 sizeof (char) == 1. Однако не всегда 1 байт равен 8 битам. Если вы хотите подсчитать количество бит в 1 байте (и у вас нет доступа к limits.h), я предлагаю следующее:
unsigned int bitnum(void) {
unsigned char c = ~0u; /* Thank you Jonathan. */
unsigned int v;
for(v = 0u; c; ++v)
c &= c - 1u;
return(v);
}
Здесь мы используем метод Кернигана для подсчета количества битов, установленных в c. Чтобы лучше понять приведенный выше код (или увидеть другие похожие), я отсылаю вас к «Bit Twiddling Хаки».
Лучше использовать ~ 0, чем -1; на машине с дополнением до единицы или знаковой величиной -1 может не быть полностью битовым. ~ 0 гарантированно будет установлен всеми битами.
@ Джонатан: В этом есть смысл. Спасибо за предложение. Я сейчас редактирую пост. (Мне очень жаль, что я так много раз редактировал этот комментарий!)
-1 всегда все биты единица. преобразование -1 в беззнаковый char не обязательно сохраняет бит (усечение)
он определен математически: -N is (2 ^ CHAR_BIT - (N mod (2 ^ CHAR_BIT))), что означает, что -1 всегда является самым высоким беззнаковым символом, имеющим все биты 1. Разница в представлении знака заключается в том, что если вы имеют дополнение до двух, преобразование здесь концептуальное: битовая комбинация не изменится:
в то время как -1 - это все биты 1 до этого, то же самое и после преобразования в беззнаковый char. придирки (мне это действительно не нравится, но, чтобы быть правильным :)), ~ 0u может (после преобразования) вместо этого привести к другому значению, чем all-bits-1: преобразование значения в unsigned char будет обернуто вокруг N = > N по модулю 2 ^ CHAR_BIT
... означает, что если N не кратно UCHAR_MAX (что может произойти, потому что беззнаковое int не должно использовать все свои биты для хранения своего значения), вы можете остаться со значением, не обязательным для всех битов 1. поэтому Я думаю, что ваша первая версия, преобразовывающая -1 в беззнаковый символ, была в порядке. пожалуйста, скажите мне, если я ошибаюсь
чтобы процитировать его напрямую: «В противном случае, если новый тип беззнаковый, значение преобразуется путем многократного добавления или вычитания на единицу большего, чем максимальное значение, которое может быть представлено в новом типе, пока значение не окажется в диапазоне нового типа. "
(говоря «-1 - это всегда все биты один», я имею в виду, что -1 преобразовано в беззнаковый символ, как в вашем ответе. -1 сам по себе, конечно, только все биты один для двух дополнений). для дополнения до двух преобразование не меняет биты. комментарии слишком короткие, чтобы говорить правду :)
Я почти уверен, что (unsigned char) -1 не установит все биты на машине, которая использует либо дополнение до единиц, либо знаковое представление чисел со знаком.
@anon: Вы можете быть уверены, но вы тоже ошибаетесь. (unsigned_type)-1 - это биты "все единицы" всегда в типе назначения.
@R: Как такое может быть? Дополнение до единицы означает, что для 16-битных целых чисел -1 равно% 11111111-11111110, потому что для получения отрицательного числа биты просто переворачиваются (глянь сюда). Только для двух дополнений -1 будет% 11111111-11111111, то есть 0x7FFFF + 1 (когда многие процессоры любезно устанавливают флаг переполнения).
@AndreasSpindler: см. Комментарий JohannesSchaub-litb: преобразование из подписанного в беззнаковый - это не просто переинтерпретация битового шаблона, концептуально вы добавляете Uxxx_MAX, пока не попадете в диапазон.
Я заметил, что некоторые ответившие изменили определение слова «байт» на что-то иное, чем 8 бит. Байт равен 8 битам, однако в некоторых реализациях c char составляет 16 бит (2 байта) или 8 бит (1 байт). Люди, которые называют байт «наименьшей адресуемой единицей памяти» или подобным мусором, потеряли понимание значения байта (8 бит). Причина того, что некоторые реализации C имеют 16-битные символы (2 байта), а некоторые - 8-битные символы (1 байт), и не существует стандартного типа, называемого «байтом», - это лень.
Итак, мы должны использовать int_8
языковой стандарт определил это значение слова «байт» как наименьшую адресуемую единицу. Это не обязательно должно быть 8 бит. В некоторых системах он может быть больше. Маловероятно, что в этих системах даже будет int_8 (или int8_t).
Не просто маловероятно. int8_t требуется, если он существует, не иметь битов заполнения (и представления дополнения до двух), поэтому единственный способ его существования - это если char имеет ровно 8 бит.
Байт традиционно нет означал 8 бит. Например: основная причина, по которой FTP использует отдельные соединения для управления и передачи данных, заключается в том, чтобы иметь возможность выбрать соответствующий размер байта для соединения для передачи данных, например, для 36-битных компьютеров. Обратите внимание, что в RFC используется термин октет (и избегайте использования неоднозначного термина «байт») для обозначения 8-битного блока данных.
Убедитесь, что вы отличаете байт от октета. sizeof (char) = 1 always, что означает, что char всегда является байтом. Однако байт не всегда является октетом (байты DEC Alpha были 10 битами, IIRC ... октеты определены как 8 бит).