【问题标题】:Bits mask - bitwise operations in C位掩码 - C 中的按位运算
【发布时间】:2017-12-17 11:05:57
【问题描述】:

例子:我有整数0000010010001110的二进制表示

我如何通过 110..... 0....... 屏蔽这些位? 我需要在掩码中保存零并保存所有活动位 在以下整数110010001110

我是位运算的新手,请给我一些想法或建议,谢谢。

更新。我需要屏蔽 wchar_t 并以 unicode (UTF-8) 输出 表示

阅读 UTF-8 规范以获取更多详细信息,但在高层次上:

代码点 0 – 007F 存储为常规的单字节 ASCII。代码 点 0080 及以上被转换为二进制并存储(编码)在 一系列字节。第一个“count”字节表示 代码点的字节,包括计数字节。这些字节开始 11..0:

110xxxxx(前导“11”表示依次为2个字节,包括 “计数”字节)

1110xxxx(1110 -> 3 个字节顺序)

11110xxx(11110 -> 4 字节顺序)

以 10... 开头的字节是“数据”字节,包含以下信息 代码点。一个 2 字节的示例如下所示

110xxxxxx 10xxxxxx

【问题讨论】:

  • 不清楚你想要实现什么。显示更多对样本输入和所需结果可能会有所帮助。您还应该展示自己所做的努力。制作minimal reproducible example 给人留下好印象。即使您不知道如何继续,您的 MCVE 也应该包含一个输入(例如一个 unsigned int 变量),其中包含您想要处理的任何内容和一个输出,例如另一个变量最终应该包含结果。
  • @Yunnosch 我试试,谢谢

标签: c unicode utf-8 bit-manipulation mask


【解决方案1】:

我需要屏蔽 wchar_t 并以 unicode (UTF-8) 表示形式输出

您是否阅读过UTF-8 in the Unicode standard(第 3.9 节 - Unicode 编码形式)或RFC 3629,甚至UTF-8 documentation on Wikipedia 的官方规范?

它们描述了将 21 位代码点编号拆分为编码字节序列所需的算法。请注意,wchar_t 在 Windows 上是 16 位 (UTF-16),但在大多数其他平台上是 32 位 (UTF-32)。 UTF 之间的转换相当简单,但您必须考虑 UTF 的实际含义,因为将 UTF-16 转换为 UTF-8 与将 UTF-32 转换为 UTF-8 有点不同。

简而言之,你需要这样的东西:

uint32_t codepoint = ...;
// This is the actual codepoint number, decoded from 1 or 2 wchar_t
// elements, depending on the UTF encoding of the wchar_t sequence.
// In UTF-32, the characters are the actual codepoint numbers as-is.
// In UTF-16, only the characters <= 0xFFFF are the actual codepoint
// numbers, the rest are encoded using surrogate pairs that you would
// have to decode to get the actual codepoint numbers...

uint8_t bytes[4];
int numBytes = 0;

if (codepoint <= 0x7F)
{
    bytes[0] = (uint8_t) codepoint;
    numBytes = 1;
}
else if (codepoint <= 0x7FF)
{
    bytes[0] = 0xC0 | (uint8_t) ((codepoint >> 6) & 0x1F);
    bytes[1] = 0x80 | (uint8_t) (codepoint & 0x3F);
    numBytes = 2;
}
else if (codepoint <= 0xFFFF)
{
    bytes[0] = 0xE0 | (uint8_t) ((codepoint >> 12) & 0x0F);
    bytes[1] = 0x80 | (uint8_t) ((codepoint >> 6) & 0x3F);
    bytes[2] = 0x80 | (uint8_t) (codepoint & 0x3F);
    numBytes = 3;
}
else if (codepoint <= 0x10FFFF)
{
    bytes[0] = 0xF0 | (uint8_t) ((codepoint >> 18) & 0x07);
    bytes[1] = 0x80 | (uint8_t) ((codepoint >> 12) & 0x3F);
    bytes[2] = 0x80 | (uint8_t) ((codepoint >> 6) & 0x3F);
    bytes[3] = 0x80 | (uint8_t) (codepoint & 0x3F);
    numBytes = 4;
}
else
{
    // illegal!
}

// use bytes[] up to numBytes as needed...

这可以简化为:

uint32_t codepoint = ...; // decoded from wchar_t sequence...

uint8_t bytes[4];
int numBytes = 0;

if (codepoint <= 0x7F)
{
    bytes[0] = 0x00;
    numBytes = 1;
}
else if (codepoint <= 0x7FF)
{
    bytes[0] = 0xC0;
    numBytes = 2;
}
else if (codepoint <= 0xFFFF)
{
    bytes[0] = 0xE0;
    numBytes = 3;
}
else if (codepoint <= 0x10FFFF)
{
    bytes[0] = 0xF0;
    numBytes = 4;
}
else
{
    // illegal!
}

for(int i = 1; i < numBytes; ++i)
{
    bytes[numBytes-i] = 0x80 | (uint8_t) (codepoint & 0x3F);
    codepoint >>= 6;
}

bytes[0] |= (uint8_t) codepoint;

// use bytes[] up to numBytes as needed...

在您的示例中,0000010010001110 是十进制 1166,十六进制 0x48E。 Codepoint U+048E 以 UTF-8 编码为字节 0xD2 0x8E,例如:

0000010010001110b -> 010010b 001110b 0xC0 或 010010b -> 0xD2 0x80 或 001110b -> 0x8E

【讨论】:

    【解决方案2】:

    不清楚你到底需要什么,但如果你需要“识别”“计数”字节和“数据”字节的类型,对于给定的例子:

    1100000110100000(11000001 10100000)

    您可以使用“识别”“计数”字节:

    #define BIT_MASK 0X8000 //which gives---1000 0000 0000 0000
    

    然后使用运算符&amp;检查是否设置了位,counter计算设置了多少位,使用&lt;&lt;运算符左移(最多8次)。如果出现未设置的位,请中断。

      #include <stdio.h>
      #include <stdint.h>
      #define BIT_MASK        0x8000
      #define MAX_LEFT_SHIFT  8
    
    int main(void)
    {
        uint16_t exm_num = 49568;// for example 11000001 10100000 in binary
        int i,count=0;
        for(i=0;i<MAX_LEFT_SHIFT;++i){
        if (exm_num & BIT_MASK)
            ++count;
         else
             break;
         exm_num = exm_num<<1;
     }
         return 0;
    }
    

    然后您可以使用count 的最终值来识别类型。

    该示例的输出为 2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-05
      • 1970-01-01
      • 2010-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多