Есть ли стандартный способ определения разрядности оборудования?

Переменные типа int якобы являются «одним машинным словом в длину», но во встроенных системах компиляторы C для 8-битного микро-использования должны иметь int из 16 бит !, (8 бит для unsigned char), а для большего количества бит int ведет себя нормально. : в 16-битном микросхеме int тоже 16 бит, а в 32-битной микросхеме int - 32 бита и т. д.

Итак, есть ли стандартный способ проверить это, например, BITSIZEOF (int)?

как "sizeof" для байтов, но для битов.

это была моя первая идея

    register c=1;                
    int bitwidth=0;
    do
    {

        bitwidth++;

    }while(c<<=1);

    printf("Register bit width is : %d",bitwidth);

Но он принимает c как int, и в 8-битных компиляторах обычно используется int как 16 бит, поэтому в результате получается 16. Кажется, нет стандарта для использования int в качестве «ширины регистра» (или это не так. уважаемый)

Почему я хочу это обнаружить? Предположим, мне нужно много переменных, для которых требуется менее 256 значений, поэтому они могут быть 8, 16, 32 битами, но использование правильного размера (такого же, как память и регистры) ускорит работу и сэкономит память, и если это невозможно решил в коде, я должен переписать функцию для каждой архитектуры

ИЗМЕНИТЬ. Прочитав ответы, я нашел эту хорошую статью.

http://embeddedgurus.com/stack-overflow/category/efficient-cc/page/4/

Приведу заключение (выделено жирным шрифтом)

Таким образом, суть в следующем. Если вы хотите начать писать эффективный переносимый встроенный код, первый шаг, который вам следует сделать, - это начать использовать типы данных C99 «минимально» и «быстро». Если ваш компилятор не совместим с C99, жалуйтесь, пока он не станет - или смените поставщика. Если вы внесете это изменение, я думаю, вы будете приятно удивлены улучшениями в размере кода и скорости, которые вы достигать.


person Hernán Eche    schedule 27.07.2010    source источник
comment
использование таких типов, как char, int, short - плохая практика и должно быть запрещено для встроенных систем. Я видел компилятор (CodeWarrior), который позволяет изменять длину каждого типа. Просто используйте заголовочный файл types.h.   -  person kmalmur    schedule 27.07.2010


Ответы (6)


Мне нужно переписать функцию для каждой архитектуры

Нет, не знаешь. Используйте stdint.h из C99, который имеет такие типы, как uint_fast8_t, который будет типом, способным быстро и быстро содержать 256 значений.

Тогда, независимо от платформы, типы изменятся соответствующим образом, и вы ничего не измените в своем коде. Если ваша платформа не имеет определенного набора, вы можете добавить свой собственный.

Намного лучше, чем переписывать каждую функцию.

person GManNickG    schedule 27.07.2010
comment
+1 это решение и более стандартное, я думаю (во всяком случае, я все еще не могу определить ширину оборудования) - person Hernán Eche; 27.07.2010
comment
@Hernan: Не удивительно. C не заботится о реализации, а ширина - это то, что нужно было бы раскрыть с помощью некоторого специфичного для ОС API. - person GManNickG; 27.07.2010
comment
Компилятор Codewarrior, похоже, не совместим с C99, я буду следовать совету embeddedgurus.com, жаловаться или менять vendor = P - person Hernán Eche; 27.07.2010
comment
Когда я начал использовать stdint.h, я никогда не оглядывался назад. Это облегчает переносимость больше всего на свете. - person Gerhard; 28.07.2010
comment
@Gerhard, мне правда хотелось бы, чтобы это было стандартно для C ++. знак равно - person strager; 01.08.2010

Чтобы ответить на ваш более глубокий вопрос более прямо, если вам нужны очень конкретные размеры хранилища, которые можно переносить между платформами, вы должны использовать что-то вроде types.h stdint.h, которое определяет типы хранилищ, указанные с количеством бит.

Например, uint32_t всегда представляет собой 32 бита без знака, а int8_t всегда представляет собой 8 битов со знаком.

person Amardeep AC9MF    schedule 27.07.2010
comment
+1 это решение (во всяком случае, я все еще не могу определить ширину оборудования) - person Hernán Eche; 27.07.2010
comment
@sbi: на странице руководства они называются целыми числами точной ширины. Но я сослался на неправильный заголовочный файл. Это не types.h, а stdint.h. Исправляю ответ. - person Amardeep AC9MF; 27.07.2010

ISA, для которой вы компилируете, уже известен компилятору, когда он запускает ваш код, поэтому лучше всего обнаружить его во время компиляции. В зависимости от вашей среды вы можете использовать все, от стиля autoconf / automake до нижнего уровня # ifdef, чтобы настроить свой код на конкретную архитектуру, на которой он будет работать.

person Luke404    schedule 27.07.2010
comment
Путь к сложному. Используйте sizeof(int) * CHAR_BIT по предложению Павла и Андрея. - person sbi; 27.07.2010

Я не совсем понимаю, что вы имеете в виду под "не существует стандарта для использования" int "как" ширина регистра ". В исходной спецификации языка C (C89 / 90) тип int подразумевается в определенных контекстах, когда явный тип не указан Ваш register c эквивалентен register int c, и это совершенно стандартно для C89 / 90. Также обратите внимание, что спецификация языка C требует, чтобы тип int поддерживал как минимум диапазон -32767 ... + 32767, что означает, что на любой платформе int будет иметь как минимум 16 битов формирования значений.

Что касается разрядности ... sizeof(int) * CHAR_BIT даст вам количество бит в объектном представлении типа int.

Теоретически, однако, не гарантируется, что представление значения типа int будет использовать все биты его объектного представления. Если вам нужно определить количество битов, используемых для представления значения, вы можете просто проанализировать значения INT_MIN и INT_MAX.

P.S. Глядя на заголовок вашего вопроса, я подозреваю, что вам действительно нужно только значение CHAR_BIT.

person AnT    schedule 27.07.2010
comment
Проблема в том, что в 16- или 8-битной архитектуре CHAR_BIT, INT_MIN и INT_MAX имеют одинаковое значение, поэтому я не могу использовать их для обнаружения, по крайней мере, в большинстве распространенных компиляторов микроконтроллеров. Я думаю, что стандарт для int, начиная с 16 бит и выше - person Hernán Eche; 27.07.2010
comment
@ Эрнан: Вы говорите, что на этих архитектурах CHAR_BIT==INT_MIN==INT_MAX? Это просто смешно! Соответствующий стандарту способ определения количества бит для любого типа T - это sizeof(T)*CHAR_BIT. - person sbi; 27.07.2010
comment
@sbi, в этом смысле они имеют одинаковое значение, CHAR_BIT (8 бит) = CHAR_BIT (16 бит), INT_MIN (8 бит) = INT_MIN (16 бит) и т. д. - person Hernán Eche; 27.07.2010
comment
@ Эрнан: Что ж, тогда char имеет одинаковый размер на обеих этих архитектурах, как и int. В чем тогда твоя проблема? - person sbi; 27.07.2010
comment
@sbi, я должен определить архитектуру, чтобы узнать, использовать ли char или int, я хотел бы иметь -посредством препроцессора выбранный тип-, который определяет мне 8-битную переменную при 8-битных регистрах и 16-битную при 16-битных регистрах , этот тип точно int для 16,32,64 .. но в 8 бит у меня проблема, что int имеет ширину 16 бит .. - person Hernán Eche; 27.07.2010
comment
Я не думаю, что стандарт C даже требует, чтобы UINT_MAX был степенью двойки. Я думаю, что у кого-то может быть соответствующий стандартам компилятор C, нацеленный на машину, где каждое число хранится в десяти счетных трубках с десятью состояниями. Вычисление логических операторов на такой машине будет очень медленным (им придется выполнять повторяющиеся операции divmod-2), но это не сделает его несовместимым со стандартами. - person supercat; 28.07.2010
comment
@supercat: Я считаю, что для этого требуется, чтобы UINT_MAX был степенью 2 минус 1. Беззнаковая арифметика в C должна быть по модулю 2 ^ N, где N - количество битов, формирующих значение, в беззнаковом типе. Это сразу означает, что максимальное значение любого беззнакового типа должно быть 2 ^ N-1. В остальном вы абсолютно правы. Допустимая реализация C может быть построена на основе троичного или десятичного аппаратного обеспечения. - person AnT; 28.07.2010
comment
@ Эрнан: Понятно. Извините за то, что был таким тупым, но я, должно быть, не понял ваш вопрос. Что ж, в конце концов, то, что вы хотите, было бы легко сделать, используя мета-шаблон C ++, но, поскольку вы застряли в C, я думаю, что <stdint.h> - это то, что вам нужно. - person sbi; 28.07.2010

Подходит ли unsigned char или unsigned short вашим потребностям? Почему бы не использовать это? Если нет, вы должны использовать флаги времени компиляции, чтобы ввести соответствующий код.

person MikeyB    schedule 27.07.2010
comment
При преобразовании в / из размера машинного слова по умолчанию возникают накладные расходы, поэтому использование настолько маленькой переменной, насколько это возможно, - не лучший способ. - person Hernán Eche; 28.07.2010

Я думаю, что в этом случае вам не нужно знать, сколько бит у вашей архитектуры. Просто используйте как можно меньше переменных, если хотите оптимизировать свой код.

person kmalmur    schedule 27.07.2010
comment
Учитывая последний абзац вопроса, я думаю, что это правильный путь. Если все ваши значения меньше 256, используйте uint8_t. Когда ваш ЦП копирует его в регистр, он подписывает и расширяет его по мере необходимости, чтобы заполнить остальную часть регистра. Вы не должны увидеть потери производительности при использовании чисел, меньших размера регистра. Лучше всего использовать наименьший тип данных из stdint.h, который может представлять все ваши значения. - person bta; 27.07.2010
comment
возможно, но я думаю, что unsigned char - самый переносимый ответ, просто потому, что stdint.h из C99, а не в предыдущем - person Hernán Eche; 27.07.2010