C语言二进制、八进制、十进制、十六进制深入探究_c语言 表示二进制数

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

#include <stdio.h>
int main()
{
    short a = 0b1010110;  //二进制数字
    int b = 02713;  //八进制数字
    long c = 0X1DAB83;  //十六进制数字
   
    printf("a=%ho, b=%o, c=%lo\n", a, b, c);  //以八进制形似输出
    printf("a=%hd, b=%d, c=%ld\n", a, b, c);  //以十进制形式输出
    printf("a=%hx, b=%x, c=%lx\n", a, b, c);  //以十六进制形式输出(字母小写)
    printf("a=%hX, b=%X, c=%lX\n", a, b, c);  //以十六进制形式输出(字母大写)
    return 0;
}

运行结果:
a=126, b=2713, c=7325603
a=86, b=1483, c=1944451
a=56, b=5cb, c=1dab83
a=56, b=5CB, c=1DAB83

从这个例子可以发现,一个数字不管以何种进制来表示,都能够以任意进制的形式输出。数字在内存中始终以二进制的形式存储,其它进制的数字在存储前都必须转换为二进制形式;同理,一个数字在输出时要进行逆向的转换,也就是从二进制转换为其他进制。

输出时加上前缀

请读者注意观察上面的例子,会发现有一点不完美,如果只看输出结果:

  • 对于八进制数字,它没法和十进制、十六进制区分,因为八进制、十进制和十六进制都包含 0~7 这几个数字。
  • 对于十进制数字,它没法和十六进制区分,因为十六进制也包含 0~9 这几个数字。如果十进制数字中还不包含 8 和 9,那么也不能和八进制区分了。
  • 对于十六进制数字,如果没有包含 a~f 或者 A~F,那么就无法和十进制区分,如果还不包含 8 和 9,那么也不能和八进制区分了。

区分不同进制数字的一个简单办法就是,在输出时带上特定的前缀。在格式控制符中加上#即可输出前缀,例如 %#x、%#o、%#lX、%#ho 等,请看下面的代码:

#include <stdio.h>
int main()
{
    short a = 0b1010110;  //二进制数字
    int b = 02713;  //八进制数字
    long c = 0X1DAB83;  //十六进制数字
   
    printf("a=%#ho, b=%#o, c=%#lo\n", a, b, c);  //以八进制形似输出
    printf("a=%hd, b=%d, c=%ld\n", a, b, c);  //以十进制形式输出
    printf("a=%#hx, b=%#x, c=%#lx\n", a, b, c);  //以十六进制形式输出(字母小写)
    printf("a=%#hX, b=%#X, c=%#lX\n", a, b, c);  //以十六进制形式输出(字母大写)
   
    return 0;
}

运行结果:
a=0126, b=02713, c=07325603
a=86, b=1483, c=1944451
a=0x56, b=0x5cb, c=0x1dab83
a=0X56, b=0X5CB, c=0X1DAB83

十进制数字没有前缀,所以不用加#。如果你加上了,那么它的行为是未定义的,有的编译器支持十进制加#,只不过输出结果和没有加#一样,有的编译器不支持加#,可能会报错,也可能会导致奇怪的输出;但是,大部分编译器都能正常输出,不至于当成一种错误。



下面来实战一下,验证一下数值在不同进制的表示下的情况

首先我们总结一下上面的内容:

  1. 各进制表示

    • 二进制表示:使用时必须以0b0B(不区分大小写)开头
    • 八进制表示:使用时必须以0开头(注意是数字 0,不是字母 o)
    • 十六进制表示:使用时必须以0x0X(不区分大小写)开头
  2. 各进制打印

    • 二进制打印:C语言没有提供打印数值二进制表示的方式
    • 八进制打印:printf(“%o”, n) printf(“%#o”, n)
    • 十进制打印:printf(“%d”, n) printf(“%#d”, n)
    • 十六进制打印:printf(“%x”, n)
  3. 基本常识:不管是哪种进制,在计算机里面都是以0/1来表示的,说的更具体一点,都是以补码的形式存在。

一、首先演示一下用不同进制来表示同一个数值
#include <stdio.h>

//该函数用来打印unsigned char的二进制表示
void printf_bin_8(unsigned char num)
{
    int k;
    unsigned char *p = (unsigned char*)&num;

    for (int k = 7; k >= 0; k--) //处理8个位
    {
        if (*p & (1 << k))
            printf("1");
        else
            printf("0");
    }
    printf("\r\n");
}

int main() {
	unsigned char a = 99;
	printf("二进制表示为:0b"); 
	printf_bin_8(a);
	printf("八进制表示为:%#o\n",a);
	printf("十进制表示为:%d\n",a);
	printf("十六进制表示为:%#x\n",a);
}

https://raw.githubusercontent.com/xkyvvv/blogpic/main/pic1/image-20210716234600063.png#pic_center
https://raw.githubusercontent.com/xkyvvv/blogpic/main/pic1/image-20210716234659589.png

二、不同进制的数据可以比较大小和进行数值运算吗?
int main() {
	int a = 99;//十进制99
	int b = 0b01100011;//二进制99
	int c = 0143;//八进制99
	int d = 0x63;//十六进制99
	
	if(a == b && b == c && c == d)
	    printf("不同进制表示的数据是可以比较的");
	
	printf("\na+b=%d",a + b);
	printf("\na-b=%d",a - b);
	printf("\na*b=%d",a * b);
	printf("\na/b=%d",a / b);
}

https://raw.githubusercontent.com/xkyvvv/blogpic/main/pic1/image-20210716235717631.png
可以看出不同进制表示的数据可以进行大小比较和运算的,其实只要我们理解了,不管什么进制表示的数据在计算机中都是以二进制补码的方式存储的。

在进行大小比较或者运算时,我们可以都将其转成同一个进制的表示就可以了。

三、八进制、十六进制的数值表示可以作为数组索引吗?
int main() {
	int a = 99;
	int b = 0b01100011;
	int c = 0143;
	int d = 0x63;
	
	int arr[100];
	arr[99] = 55;
	printf("%d",arr[a]);
	printf("\n%d",arr[b]);
	printf("\n%d",arr[c]);
	printf("\n%d",arr[d]);
	printf("\n%d",arr[0b01100011]);
	printf("\n%d",arr[0143]);
	printf("\n%d",arr[0x63]);
}

在这里插入图片描述

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值