Управление битовым полем в C

Для этого без использования Boost можно получить указатель на строку C с помощью c_str() и использовать strcasecmp:

std::string str1 ="aBcD";
std::string str2 = "AbCd";;
if (strcasecmp(str1.c_str(), str2.c_str()) == 0)
{
    //case insensitive equal 
}
46
задан Valentin Lorentz 10 May 2014 в 16:43
поделиться

16 ответов

Битовые поля не так переносимы, как вы думаете, поскольку «C не гарантирует упорядочения полей в машинных словах» ( Книга C )

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

38
ответ дан 26 November 2019 в 20:00
поделиться

Как правило, легче читать и понимать тот, который также легче поддерживать. Если у вас есть коллеги, которые плохо знакомы с C, «более безопасный» подход, вероятно, будет для них более легким для понимания.

1
ответ дан 26 November 2019 в 20:00
поделиться

Когда я гуглил "операторы c"

Первые три страницы:

http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/V40F_HTML/AQTLTBTE/DOCU_059.HTM http://www.cs.mun.ca/~michael/c/op.html

.. поэтому я думаю, что этот аргумент о людях, плохо знакомых с языком, немного глуп.

2
ответ дан 26 November 2019 в 20:00
поделиться

Ваш первый способ предпочтительнее, ИМХО. Зачем скрывать проблему? Игра с битами - действительно простая вещь. C сделал это правильно. Порядок байтов не имеет значения. Единственное, что делает союзный раствор, - это называет вещи. 11 может показаться загадочным, но #defined для значимого имени или enum'ed должно быть достаточно.

Программисты, не умеющие обращаться с такими основами, как "| & ^ ~", вероятно, ошибаются в своей работе.

3
ответ дан 26 November 2019 в 20:00
поделиться

В C ++ просто используйте std :: bitset .

5
ответ дан 26 November 2019 в 20:00
поделиться

Сообщение в блоге , на которое вы ссылаетесь, упоминает необработанное поле объединения в качестве альтернативного метода доступа для битовых полей.

Цели, которые использовал автор сообщения в блоге raw for подходят, однако, если вы планируете использовать его для чего-нибудь еще (например, сериализации битовых полей, установки / проверки отдельных битов), катастрофа ждет вас не за горами. Порядок битов в памяти зависит от архитектуры, а правила заполнения памяти меняются от компилятора к компилятору (см. wikipedia ), поэтому точное положение каждого битового поля может отличаться, другими словами, вы никогда не можете быть уверены, какой бит raw каждому битовому полю соответствует.

Однако, если вы не планируете смешивать его, лучше уберите raw , и вы будете в безопасности.

6
ответ дан 26 November 2019 в 20:00
поделиться

В любом случае битовые поля использовались в программном обеспечении GNU на протяжении десятилетий, и это не причинило им никакого вреда. Мне они нравятся как параметры функций.

Я бы сказал, что битовые поля обычные , а не структуры. Все знают, как И значения, чтобы установить различные параметры, и компилятор сводит это к очень эффективным побитовым операциям на ЦП.

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

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

6
ответ дан 26 November 2019 в 20:00
поделиться

Что в подходе битового поля заставляет вас съеживаться?

Оба метода имеют свое место, и единственное решение, которое у меня есть, - какой из них использовать:

Для простого "одного" -off "битовая игра, я использую побитовые операторы напрямую.

Для чего-то более сложного - например, сопоставления аппаратных регистров, подход битовых полей выигрывает без труда.

  • Битовые поля более лаконичны в использовании (за счет / немного / больше подробность записи.
  • Битовые поля более надежный (какой размер "int", в любом случае)
  • Битовые поля обычно просто так же быстро, как побитовые операторы.
  • Битовые поля очень эффективны, когда вы иметь сочетание одного и нескольких битов поля, и извлечение многобитовое поле включает в себя множество ручные переключения.
  • Битовые поля эффективно самодокументирующий. По определение структуры и, следовательно, называя элементы, я знаю, что это предназначено для выполнения.
  • Битовые поля также легко обрабатывают структуры, размер которых превышает один int.
  • С побитовыми операторами типичной (плохой) практикой является множество #defines для битовых масок.

  • Единственное предостережение с битовыми полями - это чтобы убедиться, что компилятор действительно упаковал объект до нужного размера. Я не могу вспомнить, определено ли это стандартом, поэтому assert (sizeof (myStruct) == N) - полезная проверка.

10
ответ дан 26 November 2019 в 20:00
поделиться

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

// off the top of my head
#define SET_BIT(val, bitIndex) val |= (1 << bitIndex)
#define CLEAR_BIT(val, bitIndex) val &= ~(1 << bitIndex)
#define TOGGLE_BIT(val, bitIndex) val ^= (1 << bitIndex)
#define BIT_IS_SET(val, bitIndex) (val & (1 << bitIndex)) 

Что делает ваш код читаемым, если вы не возражаете, что val должно быть lvalue, за исключением BIT_IS_SET. Если это не делает тебя счастливым, затем вы берете присвоение, заключаете его в скобки и используете как val = SET_BIT (val, someIndex); что будет эквивалентно.

На самом деле, ответ состоит в том, чтобы рассмотреть возможность отделения того, что вы хотите, от того, как вы хотите это делать.

29
ответ дан 26 November 2019 в 20:00
поделиться

Что ж, вы не ошибетесь с отображением структуры, поскольку оба поля доступны, их можно использовать взаимозаменяемо.

Одно из преимуществ битовых полей состоит в том, что вы можете легко агрегировать параметры:

mask = USER|FORCE|ZERO|COMPAT;

vs

flags.user = true;
flags.force = true;
flags.zero = true;
flags.compat = true;

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

Но иногда установка flag.blah и отображение всплывающего списка в вашей среде IDE - это здорово, особенно если вы, как и я, не можете вспомнить имя флага, который хотите установить, не обращаясь постоянно к списку.

Я лично буду иногда уклоняются от объявления логических типов, потому что в какой-то момент я

6
ответ дан 26 November 2019 в 20:00
поделиться

Вы должны думать об этом с точки зрения писателя - знайте свою аудиторию. Итак, есть пара «аудиторий», которые следует учитывать.

Во-первых, есть классический программист на C, который всю свою жизнь замаскировал битовую маску и мог делать это во сне.

Во-вторых, это новичок, который понятия не имеет, что все это |, & прочее. Они программировали php на своей последней работе, а теперь работают на вас. (Я говорю это как новичок, который занимается php)

Если вы напишете, чтобы удовлетворить первую аудиторию (то есть с битовой маской в ​​течение всего дня), вы сделаете их очень счастливыми, и они смогут поддерживать код с завязанными глазами. Однако новичкам, вероятно, придется преодолеть большую кривую обучения, прежде чем они смогут поддерживать ваш код. Им нужно будет узнать о бинарных операторах, как вы используете эти операции для установки / очистки битов и т. д. Вы почти наверняка столкнетесь с ошибками, введенными newb, поскольку он / она все уловки, необходимые, чтобы заставить это работать.

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

 flags.force = 0;

, чем

 flags &= 0xFFFFFFFE;

, и первая аудитория будет просто сварливой, но трудно представить, что они не смогли бы разобраться и поддерживать новый синтаксис. Просто облажаться намного сложнее. Новых ошибок не будет, потому что newb будет легче поддерживать код. Вы просто будете читать лекции о том, что «в свое время вам требовались твердая рука и намагниченная игла для установки бит ... у нас даже не было битовых масок!» (спасибо XKCD ).

19
ответ дан 26 November 2019 в 20:00
поделиться

Да, это подвержено ошибкам. Я видел много ошибок в этом коде, главным образом потому, что некоторые люди считают, что им следует возиться с ним и бизнес-логикой совершенно неорганизованным образом, создавая кошмары обслуживания. Они думают, что «настоящие» программисты могут писать value | = mask; , value & = ~ mask; или даже хуже в любом месте, и это нормально . Еще лучше, если есть какой-нибудь оператор приращения, пара memcpy , приведение указателей и любой непонятный и подверженный ошибкам синтаксис, который приходит им в голову в то время. Конечно, нет необходимости быть последовательным, и вы можете переключать биты двумя или тремя разными способами, распределенными случайным образом.

Мой совет был бы таков:

  1. Инкапсулируйте это ---- в классе, с такими методами, как SetBit (...) и ClearBit (...) . (Если у вас нет классов в C, в модуле.) Пока вы работаете, вы можете задокументировать все их поведение.
  2. Модульное тестирование этого класса или модуля.
4
ответ дан 26 November 2019 в 20:00
поделиться

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

Как только вы привыкнете к этому, используйте маски является простым, однозначным и переносимым.

Битовые поля просты, но их нельзя переносить без выполнения дополнительной работы.

Если вам когда-либо придется писать MISRA -совместимый код, рекомендации MISRA недовольны о битовых полях, объединениях и многих, многих других аспектах C, чтобы избежать неопределенного или зависимого от реализации поведения.

2
ответ дан 26 November 2019 в 20:00
поделиться

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

 #define  ASSERT_GPS_RESET()                    { P1OUT &= ~GPS_RESET ; }

, кстати, ваше определение объединения в исходном вопросе не будет работать с моей комбинацией процессор / компилятор. Тип int имеет ширину всего 16 бит, а определения битового поля - 32. Чтобы сделать его немного более переносимым, вам нужно будет определить новый 32-битный тип, который затем можно будет сопоставить с требуемым базовым типом в каждой целевой архитектуре как часть упражнение по портированию. В моем случае

typedef   unsigned long int     uint32_t

и в исходном примере

typedef unsigned int uint32_t

typedef union {
        struct {
                boolean_t user:1;
                boolean_t zero:1;
                boolean_t force:1;
                int :28;                /* unused */
                boolean_t compat:1;     /* bit 31 */
        };
        uint32_t raw;
} flags_t;

наложенный int также должен быть беззнаковым.

2
ответ дан 26 November 2019 в 20:00
поделиться

Использование union имеет неопределенное поведение в соответствии со стандартом ANSI C, и поэтому его не следует использовать (или, по крайней мере, не считать переносимым).

Из ISO / Стандарт IEC 9899: 1999 (C99) :

Приложение J - Проблемы переносимости:

1 Следующее не указано:

- Значение байтов заполнения при сохранении значений в структурах или объединениях (6.2.6.1 ).

- Значение члена объединения, отличное от последнего, сохраненное в (6.2.6.1).

6.2.6.1 - Основные понятия языка - Представление типов - Общие:

6 Когда значение сохраняется в объекте структуры или типа объединения, в том числе в члене объекта, байты представления объекта, соответствующие любым байтам заполнения, принимают неуказанные значения. [42]) Значение объекта структуры или объединения никогда не является ловушкой. представление, даже если значение члена структуры или объекта объединения может быть представление прерывания.

7 Когда значение сохраняется в члене объекта типа union, байты объекта представления, которые не соответствуют этому члену, но соответствуют другим членам принимать неуказанные значения.

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

14
ответ дан 26 November 2019 в 20:00
поделиться

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

23
ответ дан 26 November 2019 в 20:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: