了解十六进制逻辑

时间:2018-09-23 06:39:56

标签: objective-c hex

在以下十六进制代码逻辑中很难理解。谁能解释开关条件中的&符,以及以前的TagSize是如何计算的。

- (void)parse:(NSInputStream*)inputStream {

  NSInteger MASK = 0x1f;
  NSInteger Type1 = 8;
  NSInteger Type2 = 9;
  NSInteger Type3 = 18;

    uint8_t header[11];
    long len = [inputStream read:header maxLength:11];

    //How does it work?
    switch (header[0] & MASK) {
        case  Type1:
            self.type = Type_1;
            break;
        case Type2:
            self.type = Type_2;
            break;
    }

    self.dataSize = ((header[1] & 0x000000FF) << 16) | ((header[2] & 0x000000FF) << 8) | (header[3] & 0x000000FF);

        // read previous tag size
    uint8_t tagSize[4];
    [inputStream read:tagSize maxLength:4];
    int previousTagSize = ((tagSize[0] & 0x000000FF) << 24) |
                          ((tagSize[1] & 0x000000FF) << 16) |
                          ((tagSize[2] & 0x000000FF) << 8) |
                          (tagSize[3] & 0x000000FF);

    if (previousTagSize != 11 + self.dataSize) {
        NSLog(@"Invalid .");
    }
}

1 个答案:

答案 0 :(得分:1)

  

在十六进制代码逻辑下很难理解。

“逻辑”不是十六进制,而是整数和按位逻辑的组合。

“十六进制”只是表示Objective-C程序文本中整数值的一种方法。无论程序文本中整数的文本表示形式如何,编译后的Objective-C在计算机上执行的顺序都是按位顺序。

  

例如,104(十进制),0x68(十六进制)和0150(八进制)(如果存储在一个字节中)都使用相同的{{1 }}。计算机还将UTF-8字符“ h”视为那些相同有序的位序列。

     

(注意:我在此答案中使用字节或8位来保存键入的大量零,在64位计算机上的01101000是64位,但用于示例中的值这里的前56位全为零。)

位是否被视为整数,浮点数,字符取决于上下文-这就是整数和按位逻辑的用处...

  

有人可以在开关状态下解释“&”符号吗?

Objective-C中的NSInteger运算符是按位和,即两个操作数中的有序位序列使用逻辑(aka布尔)和函数({ {1}},&0 and 0 = 00 and 1 = 0)。代码片段:

1 and 0 = 0

使用1 and 1 = 1进行 masking 操作-如果您查看函数,如果一个操作数是header[0] & MASK ,则结果为另一个操作数,如果为&,则结果为1,因此可以用于“屏蔽”序列的一部分。

  

例如,考虑如果0从上方持有我们104的表示形式,则该表示形式为8位为0header[0]的表示形式,其值为01101000,为8位,是MASK。使用按位合并这两种表示,并给出序列0x1F,其中前3个零是由于第二个操作数(“掩码”)中的零引起的,而5位序列00011111与由于第二个操作数全为1,因此第一个操作数的后五位为

。      

按位排列之后,如果将所得的位序列解释为整数,则值为00001000,恰好与程序中的01000相同。

因此,8的作用是基于Type1的后5位的整数解释进行选择。例如,当将多个数据值打包到较大的存储单元中时发生这种类型的代码-在这种情况下,64位中的5位(64位计算机上switch的存储大小)。

  

以及以前的TagSize的计算方式。

同样,这只是按位运算,运算符header[0]按位或,运算符NSInteger左移,只剩下一位shift丢弃有序位序列的最左位,并在最右端附加一个|位(因此该序列保持相同的长度)。完整的片段:

<<

将4个值(每个值被屏蔽为8位[*])组合为一个32位(Objective-C中0的大小)。

HTH

[*]如果该值是带符号类型,则即使该值适合目标位数以除去多余的位(以4位二进制补码表示形式{{1 }}代表5,int previousTagSize = ((tagSize[0] & 0x000000FF) << 24) | ((tagSize[1] & 0x000000FF) << 16) | ((tagSize[2] & 0x000000FF) << 8) | (tagSize[3] & 0x000000FF); 代表-3;在8位中分别为int0101,在第二种情况下,掩码会删除那些多余的1,否则它们将影响包装。拆下的1's会在拆箱后恢复。请阅读2's的补码以获取更多详细信息。