难得有时间写一篇关于C语言的博客呢,虽然说标题是C语言取高位低位,但不仅限于C语言。

假设我们有一个char类型i变量,数值是235 16进制是0xEB,二进制是1110-1011。

假设我们需要读取1110,也就是235的高位你会怎么做? 大多数人应该是用位移吧?235»4,得到1110,0x0E 但这种算法仅限于静态类型语言,如果是动态类型语言该怎么算呢?下面提供3种思路在动态静态类型语言中获取高低位。



通用方法

1. 使用按位与和位移运算

char ch = 0xEB // 235
char high = (ch & 0xF0) >> 4 // 高位
char low = ch & 0x0F // 低位

这个方法比较简单,适用于非静态语言 原理是0xF0二进制是1111-0000,进行按位与 运算以后其中低4位变成0000,高4位保留

我们先计算出235的2进制:
这里有个技巧把一个数减去最大的128,得到n,假设n是32, 那么我们直接写出第3位为1,如果是35,那么我们可以再对其 进行分割为32 + 2 + 1的组合得到1010-0011

235 = 128 + 107
= 128 + 64 + 43
= 128 + 64 + 32 +  11
= 128 + 64 + 32 + 8 + 3
= 128 + 64 + 32 + 8 + 2 + 1

按照这个过程,235算出来是 1110-1011
1110-1011 & 1111-0000 = 1110-0000
1110-0000 » 4 = 0000-1110 = 14

2. 使用取余运算

char temp=0x86
char high=(temp-temp%0x10)/0x10
char low=temp%0x10

这个相对比较复杂吧,我们先看括号里的temp-temp%0x10 temp-temp%0x10,括号里是先对temp除16取余,结果在0~15 也就是0000~1111之间(4位),然后temp-temp%0x10则是减去temp 本身的低4位,保留高位。括号外则是/0x10,结果也是0~15 合起来在看确实是个很不错的设计,在没有移位运算的平台非常实用。

Q: 如果本身连取余都没有呢?
A: 如果取余都没有的话可以使用除法自己实现。

仅限静态语言

1. 使用强制类型转换

看到强制类型转换各位应该明白这个不适用于弱类型语言了吧?

#include <stdio.h>

int main() {
    uint16_t i = 0, j = 0;
    for (i = 512, j = 0; i < 1536; i += 8, j++) {
        // printf("0x%04X\t",i); 
	printf("$%02X,$%02X", (char)i, i >> 8);
        if ((j%2 == 1))
            printf("\n");
	else
	    printf(",");
    }
}

这个程序原本是我用来计算6502asm里虚拟机显存的Block分割的 我用uint16_t储存16位的地址,也就相当于是两个8位数, 然后在printf(“$%02X,$%02X”, (char)i, i » 8);可以看到(char)i对i进行了 强制转换,丢失了8位数后便是我们需要的低位地址。 (6502大部分都是8位寄存器,寻址时先读取低位。)

6502asm汇编器:点击我跳转

最后提前祝大家圣诞节快乐!:)