查看原文
其他

C语言数值常量的“那些事”(细节分析)

bug菌 最后一个bug 2021-01-31

简单说说主题

    应该说本篇文章主要内容是之前向大家推送的一篇叫《字符常量的"前-中-后"字符理解》文章的加强版本,因为每篇文章都是作者认真创作的作品,目的是为了传递更多的知识经验给大家,然而可能之前该文章内容上比较枯燥等等原因,大家浏览量微乎及微,所以这里我想重新撰写该文章,让大家能够更好的注意这些细节等等。

    本篇文章主要是讲在我们C语言中,可能我们经常在数字的前面或者后面看到一些符号,比如说我们比较熟悉的0xFF就表示16进制的数字等等。可能我们在阅读代码中遇到一些我们不太理解的符号我们也不会去理会它的具体含义,比如#define REGISTER 12345u那这个u代表什么意思到底会对程序产生怎样的影响?我们在什么情况下需要在这些数字的前面或者后面加入这些字符?下面将从几个方面一一为大家总结这些在数值常量中间的字符。

字符在“前”

    “字符在前”的数值常量的情况一般都是进制类常量,那么大部分会想到二进制、十进制、八进制和16进制,然而在我们平时编程中使用比较多的就属十进制和16进制,那么二进制和八进制的数值常量如何表示呢?

    1)对于八进制,十进制、16进制以及浮点的数值常量C语言是有明确规定的

16进制:由0x或者0X开头,由0~9,A~F或a~f组成。

八进制:由数字0开头,0~7组成。

十进制:开头可以使用+-号,0~9组成。

浮点型:开头可以使用+-号,数字0~9及点号组成。

(疏漏再补)

    2)然而标准的C语言对二进制并没有并没有规定具体的格式,不过在部分编译器中厂家会自行扩展一些二进制格式,比如0b0100表示10进制4。至于为什么没有规定二进制主要的原因我觉得应该是其可读性差并且难以维护且均可以用16进制代替

    3)可能有些小伙伴们在做一些特殊的项目中觉得用二进制会的使得程序更能让程序清晰明了,那我们呢有没有办法创造这样的代码来供我们使用呢?一方面厂家如果支持肯定是最好了,如果支持不了可以参考如下代码(由于代码长度比较长,作者把代码附在文章后面以免影响大家阅读文章,里面用到了很多小技巧,不要错过)

字符在“中”

    字符在中间的数值常量可能大家都用得比较少,做算法的各位同志们用得比较多,那就是我们的科学记数法

    科学计数法:例如1e-10,表示的是1.0*10的-10次方。e的前面是整数部分,e的后面是10的次数部分

注意事项

1)计数法中的e可大写可小写;

2)e前后必须有数字,可正可负可为0,不可省略;

3)e后面必须为整数,不能存在变量(可正可负,正号可以省略)。

 科学计数法内容不多,大家只要平时记得有这样一种表达即可,以后阅读相关代码不至于非常陌生!

字符在“后”

 这篇文章的重点也就是主要讲值常量字符在后的形式!我们经常看到如132424245ul3.141592f的数值形式,或者是单片机的地址宏定义数值后面加ul,如0xA80000ul,可能有些小伙伴还觉得不信有这种用法,于是我特意找了一下大家用得比较多的stm32固件库里面的几行代码供大家参考:

    比如说上面16进制后面为什么要加上UL?可能有很多小伙伴们都看到过这样的数值常量形式,大多都没有深究也就当个普通常量来使用了,既然有人这样写了必定有他的意义,下面我就为大家总结了一下供大家参考:(看了以后可以在不懂的小伙伴们面前吹一吹了!说笑了!)

    1)u或者l(l,u,f大小写均可)在整形数值后面分别表示unsigned int 和long int;同样ul(大写的UL亦可)组合起来表示unsigned long,而不是默认int型

    2)同样f或者F作为后缀,表示的是float型。而不是默认double

    3)如果l放在小数后面表示该数值为double型。

    这样做的意义是什么?

    1)u显式的声明为无符号型,防止编译器对齐进行处理,比如移位的时候添加0还是添加1的问题。

    2)l表示长整形,也是为了防止编译器将数据截断或者强制转化而溢出,所以进行声明加l。

    3)使用f表示float仅占用4个字节,这样可以减少存储设备的空间占用。(这里提到了节省,所以大家可以做下笔记,以后项目中需要省成本就的这样挤牙膏了!)

    好了,今天的内容就这么多了,欢迎大家关注公众号"最后一个bug",哦,突然写到这里忘记了一件大事,“附二进制实现代码马上贴上。

/****************************************
*  Fuction:宏定义区
*  Note   :将两位的16进制与8位的二进制对上
****************************************/
#define HEX00000000 00
#define HEX00000001 01
#define HEX00000010 02
#define HEX00000011 03
#define HEX00000100 04
#define HEX00000101 05
#define HEX00000110 06
#define HEX00000111 07
#define HEX00001000 08
#define HEX00001001 09
#define HEX00001010 0A
#define HEX00001011 0B
#define HEX00001100 0C
#define HEX00001101 0D
#define HEX00001110 0E
#define HEX00001111 0F
#define HEX00010000 10
#define HEX00010001 11
#define HEX00010010 12
#define HEX00010011 13
#define HEX00010100 14
#define HEX00010101 15
#define HEX00010110 16
#define HEX00010111 17
#define HEX00011000 18
#define HEX00011001 19
#define HEX00011010 1A
#define HEX00011011 1B
#define HEX00011100 1C
#define HEX00011101 1D
#define HEX00011110 1E
#define HEX00011111 1F
#define HEX00100000 20
#define HEX00100001 21
#define HEX00100010 22
#define HEX00100011 23
#define HEX00100100 24
#define HEX00100101 25
#define HEX00100110 26
#define HEX00100111 27
#define HEX00101000 28
#define HEX00101001 29
#define HEX00101010 2A
#define HEX00101011 2B
#define HEX00101100 2C
#define HEX00101101 2D
#define HEX00101110 2E
#define HEX00101111 2F
#define HEX00110000 30
#define HEX00110001 31
#define HEX00110010 32
#define HEX00110011 33
#define HEX00110100 34
#define HEX00110101 35
#define HEX00110110 36
#define HEX00110111 37
#define HEX00111000 38
#define HEX00111001 39
#define HEX00111010 3A
#define HEX00111011 3B
#define HEX00111100 3C
#define HEX00111101 3D
#define HEX00111110 3E
#define HEX00111111 3F
#define HEX01000000 40
#define HEX01000001 41
#define HEX01000010 42
#define HEX01000011 43
#define HEX01000100 44
#define HEX01000101 45
#define HEX01000110 46
#define HEX01000111 47
#define HEX01001000 48
#define HEX01001001 49
#define HEX01001010 4A
#define HEX01001011 4B
#define HEX01001100 4C
#define HEX01001101 4D
#define HEX01001110 4E
#define HEX01001111 4F
#define HEX01010000 50
#define HEX01010001 51
#define HEX01010010 52
#define HEX01010011 53
#define HEX01010100 54
#define HEX01010101 55
#define HEX01010110 56
#define HEX01010111 57
#define HEX01011000 58
#define HEX01011001 59
#define HEX01011010 5A
#define HEX01011011 5B
#define HEX01011100 5C
#define HEX01011101 5D
#define HEX01011110 5E
#define HEX01011111 5F
#define HEX01100000 60
#define HEX01100001 61
#define HEX01100010 62
#define HEX01100011 63
#define HEX01100100 64
#define HEX01100101 65
#define HEX01100110 66
#define HEX01100111 67
#define HEX01101000 68
#define HEX01101001 69
#define HEX01101010 6A
#define HEX01101011 6B
#define HEX01101100 6C
#define HEX01101101 6D
#define HEX01101110 6E
#define HEX01101111 6F
#define HEX01110000 70
#define HEX01110001 71
#define HEX01110010 72
#define HEX01110011 73
#define HEX01110100 74
#define HEX01110101 75
#define HEX01110110 76
#define HEX01110111 77
#define HEX01111000 78
#define HEX01111001 79
#define HEX01111010 7A
#define HEX01111011 7B
#define HEX01111100 7C
#define HEX01111101 7D
#define HEX01111110 7E
#define HEX01111111 7F
#define HEX10000000 80
#define HEX10000001 81
#define HEX10000010 82
#define HEX10000011 83
#define HEX10000100 84
#define HEX10000101 85
#define HEX10000110 86
#define HEX10000111 87
#define HEX10001000 88
#define HEX10001001 89
#define HEX10001010 8A
#define HEX10001011 8B
#define HEX10001100 8C
#define HEX10001101 8D
#define HEX10001110 8E
#define HEX10001111 8F
#define HEX10010000 90
#define HEX10010001 91
#define HEX10010010 92
#define HEX10010011 93
#define HEX10010100 94
#define HEX10010101 95
#define HEX10010110 96
#define HEX10010111 97
#define HEX10011000 98
#define HEX10011001 99
#define HEX10011010 9A
#define HEX10011011 9B
#define HEX10011100 9C
#define HEX10011101 9D
#define HEX10011110 9E
#define HEX10011111 9F
#define HEX10100000 A0
#define HEX10100001 A1
#define HEX10100010 A2
#define HEX10100011 A3
#define HEX10100100 A4
#define HEX10100101 A5
#define HEX10100110 A6
#define HEX10100111 A7
#define HEX10101000 A8
#define HEX10101001 A9
#define HEX10101010 AA
#define HEX10101011 AB
#define HEX10101100 AC
#define HEX10101101 AD
#define HEX10101110 AE
#define HEX10101111 AF
#define HEX10110000 B0
#define HEX10110001 B1
#define HEX10110010 B2
#define HEX10110011 B3
#define HEX10110100 B4
#define HEX10110101 B5
#define HEX10110110 B6
#define HEX10110111 B7
#define HEX10111000 B8
#define HEX10111001 B9
#define HEX10111010 BA
#define HEX10111011 BB
#define HEX10111100 BC
#define HEX10111101 BD
#define HEX10111110 BE
#define HEX10111111 BF
#define HEX11000000 C0
#define HEX11000001 C1
#define HEX11000010 C2
#define HEX11000011 C3
#define HEX11000100 C4
#define HEX11000101 C5
#define HEX11000110 C6
#define HEX11000111 C7
#define HEX11001000 C8
#define HEX11001001 C9
#define HEX11001010 CA
#define HEX11001011 CB
#define HEX11001100 CC
#define HEX11001101 CD
#define HEX11001110 CE
#define HEX11001111 CF
#define HEX11010000 D0
#define HEX11010001 D1
#define HEX11010010 D2
#define HEX11010011 D3
#define HEX11010100 D4
#define HEX11010101 D5
#define HEX11010110 D6
#define HEX11010111 D7
#define HEX11011000 D8
#define HEX11011001 D9
#define HEX11011010 DA
#define HEX11011011 DB
#define HEX11011100 DC
#define HEX11011101 DD
#define HEX11011110 DE
#define HEX11011111 DF
#define HEX11100000 E0
#define HEX11100001 E1
#define HEX11100010 E2
#define HEX11100011 E3
#define HEX11100100 E4
#define HEX11100101 E5
#define HEX11100110 E6
#define HEX11100111 E7
#define HEX11101000 E8
#define HEX11101001 E9
#define HEX11101010 EA
#define HEX11101011 EB
#define HEX11101100 EC
#define HEX11101101 ED
#define HEX11101110 EE
#define HEX11101111 EF
#define HEX11110000 F0
#define HEX11110001 F1
#define HEX11110010 F2
#define HEX11110011 F3
#define HEX11110100 F4
#define HEX11110101 F5
#define HEX11110110 F6
#define HEX11110111 F7
#define HEX11111000 F8
#define HEX11111001 F9
#define HEX11111010 FA
#define HEX11111011 FB
#define HEX11111100 FC
#define HEX11111101 FD
#define HEX11111110 FE
#define HEX11111111 FF

/****************************************
*  Fuction:宏定义区
*  Note   :1)通过拼接符##,把字符串01拼成HEX开头的宏定义
            2)把宏定义转化成对应的16进制两位
            3)然后继续把多个两位16进制拼接成真正的16进制数值(多个byte)
****************************************/
#define __Bin8(BYTE0)            0x##BYTE0
#define _Bin8(BYTE0)             __Bin8(BYTE0)
#define Bin8(BYTE0)              _Bin8(HEX##BYTE0)
////////////////////////////////////////////////////////////////
#define __A8(BYTE0)              BYTE0
#define _A8(BYTE0)               __A8(BYTE0)
#define A8(BYTE0)               _A8(HEX##BYTE0)
////////////////////////////////////////////////////////////////
#define __Bin16(BYTE1, BYTE0)    BYTE1##BYTE0
#define _Bin16(BYTE1, BYTE0)     __Bin16(BYTE1, BYTE0)
#define Bin16(BYTE1, BYTE0)      _Bin16(Bin8(BYTE1),A8(BYTE0))
////////////////////////////////////////////////////////////////
#define __Bin32(BYTE3, BYTE2, BYTE1, BYTE0)  BYTE3##BYTE2##BYTE1##BYTE0
#define _Bin32(BYTE3, BYTE2, BYTE1, BYTE0)  __Bin32(BYTE3, BYTE2, BYTE1, BYTE0)
#define Bin32(BYTE3, BYTE2, BYTE1, BYTE0)   _Bin32(Bin8(BYTE3),A8(BYTE2),A8(BYTE1),A8(BYTE0))

//测试程序
int main()
{
    int testbin1  = Bin8(01010101);
    int testbin2  = Bin16(01010101,10101010);
    int testbin3  = Bin32(01010101,10101010,11111111,00000000);
   
    printf("0x%X\n", testbin1);
    printf("0x%X\n", testbin2);
    printf("0x%X\n", testbin3);
    printf("欢迎关注公众号:最后一bug");

    return 0;
}

运行结果如下:(其实原理上就是拼接成16进制,具体实现参考代码吧)

    好了,今天的内容就到就讲到这里,欢迎关注公众号:"最后一个bug",后续还会为大家整理和分享更多的编程技巧和经验,也欢迎大家分享转发!谢谢!

推荐阅读

嵌入式编程之动态接口技术(经验干货)

嵌入式编程之"重构"代码(C语言版本)

嵌入式编程必备之多方法测定程序运行时间(经验篇)

单片机常用程序框架之分时轮询(详注代码)

看门狗你确定会用了?(经验干货满满)

单片机开发之节省内存大法(C语言版本)

一种 “ 超强 ” 队列的C语言实现(附代码)

一文搞定通信协议中CRC校验(附代码)

【连载】嵌入式测试驱动开发(9)


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存