Используя откусывание (переменные на 4 бита) в C/C++ окон

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

DECLARE @Ugedagnr VARCHAR(10) = '1',
    @ModulID VARCHAR(10),
    @ModulID2 VARCHAR(10);

IF @Ugedagnr = '1'
BEGIN
    IF @Ugedagnr = '1'
    BEGIN
        SET @ModulID = 'S1';
        SET @ModulID2 = 'S2';
    END;

    IF @Ugedagnr = '2'
    BEGIN
        SET @ModulID = 'S5';
        SET @ModulID2 = 'S6';
    END;

    IF @Ugedagnr = '3'
    BEGIN
        SET @ModulID = 'S9';
        SET @ModulID2 = 'S10';
    END;
    IF @Ugedagnr = '4'
    BEGIN
        SET @ModulID = 'S13';
        SET @ModulID2 = 'S14';
    END;
    IF @Ugedagnr = '5'
    BEGIN
        SET @ModulID = 'S17';
        SET @ModulID2 = 'S18';
    END;

    SELECT @ModulID, @ModulID2


    BEGIN TRANSACTION
                    @ModulID = 'S9'
                    @ModulID2 = 'S10'
                    INSERT INTO Undervisning (ModulID, SkemaDato, LokaleID, HoldID, FagID, LaererID, Aar, Uge)
                    VALUES (@ModulID, GETDATE(), @lokaleID, @holdID, @fagID, @laererID, @CurrentYear, @WeekNumber)
                    INSERT INTO Undervisning (ModulID, SkemaDato, LokaleID, HoldID, FagID, LaererID, Aar, Uge)
                    VALUES (@ModulID2, GETDATE(), @lokaleID, @holdID, @fagID, @laererID, @CurrentYear, @WeekNumber) 
    COMMIT TRANSACTION
END;
19
задан Eric 14 May 2009 в 14:15
поделиться

5 ответов

Поскольку память имеет байтовую адресацию, вы не можете адресовать какие-либо единицы меньше одного байта. Однако вы можете создать структуру , которую хотите отправить по сети, и использовать битовые поля следующим образом:

struct A {
   unsigned int nibble1 : 4;
   unsigned int nibble2 : 4;
};
34
ответ дан 30 November 2019 в 02:20
поделиться

Расширяя ответ Мехрдада, также используйте объединение с байтом, чтобы избежать некоторых зловещих приведений:

union Nibbler {
     struct { 
        unsigned int first:4;
        unsigned int second:4;
     } nibbles;
     unsigned char byte_value;
}
16
ответ дан 30 November 2019 в 02:20
поделиться

Использовать поля в структуре:

struct Header
{
    unsigned int lowestNibble : 4;
    unsigned int anotherNibble : 4;
    unsigned int : 18;                 # Unnamed padding.
    bool aBool : 1;
    bool anotherBool : 1;
    unsigned int highestNibble : 4;
};

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

Обычно вы приводите указатель на свои данные к Header * , а затем выполняете что-то вроде:

pHeader->lowestNibble = 5;
3
ответ дан 30 November 2019 в 02:20
поделиться

Кажется, всем нравится использовать для этого битовые поля в структурах struct . Лично я оборачиваю весь код своего пакета в объекты, чтобы вы не видели кишок. Проблема, которую я обнаружил при использовании битовых полей для кода протокола, заключается в том, что он поощряет использование структур в качестве наложений в памяти. Вы можете сделать это безопасно, но вы должны быть крайне осторожны, чтобы правильно решить проблемы с порядком байтов и упаковкой. Если у вас действительно нет веской причины (например, вы пишете код, который получает пакет Ethernet из области ввода-вывода, отображенной в памяти), то использование битовых полей, наложенных на память, создает чрезвычайно хрупкий код IMHO.

Я нахожу это Намного проще написать класс Packet , который реализует процедуры извлечения, вставки и перезаписи с различной битовой шириной. Затем вы реализуете свой код обработки пакетов с точки зрения извлечения значений определенной ширины из смещений в собственные целые числа, а что нет. Скрывайте за абстракцией все вопросы, связанные с порядком байтов и упаковкой, до тех пор, пока профилирование не докажет, что накладные расходы слишком велики, чтобы нести их.

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

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

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

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

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

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

Нет, удобных типов полубайтов нет. Но их легко сделать с помощью макросов или шаблонных функций. Это хорошо работает, особенно если / когда вам нужно иметь дело с порядком байтов.

Foredecker

-2
ответ дан 30 November 2019 в 02:20
поделиться
Другие вопросы по тегам:

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