进击的小白Day015——char与int互相转换

今天意外发现一个char和int互相转换的方法,但其实到现在我还不是能够很好的理解这个过程,所以写写笔记来理一下思路,花了接近一天的时间研究这个,是因为之前写的Socket程序中用到了char和int转换,但那里面是用函数来实现的,而且精度有损,这个方法相比之前的来说应该是可以达到无损转换的。今天先写一个char和int的转换,明天再写一下double和int的转换。

今天才发现,现在自己的编程仅仅局限在宏观层面,只知道一些基本的很宏大的东西大概该怎么用,像函数、数组、指针、语句,但对一些微观层面的,比如位操作、内存操作这些方面欠缺很多,char和int的转换就涉及到位操作的知识,趁机补一补。

先贴代码把:

#include <stdio.h> typedef unsigned char UINT8; typedef int UINT32; int main(void) { int i = 0; UINT8 msg[4]; UINT32 = 1246, dest; msg[i] = (UINT8)((src & 0xff000000) >> 24); i++; msg[i] = (UINT8)((src & 0xff0000) >> 16); i++; msg[i] = (UINT8)((src & 0xff00) >> 8); i++; msg[i] = (UINT8)(src & 0xff); i++; printf('msg[0]=%x msg[1]=%x msg[2]=%x msg[3]=%x\n', msg[0], msg[1], msg[2], msg[3]); printf('msg[0]<<24=%x msg[1]<<16=%x msg[2]<<8=%x msg[3]=%x\n', msg[0] << 24, msg[1] << 16, msg[2] << 8, msg[3]); dest = (msg[0] << 24) + (msg[1] << 16) + (msg[2] << 8) + msg[3]; printf('dest=%d\n', dest); }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

分两部分介绍,int→unsigned char和unsigned char→int,先说一下,unsigned char是1个字节,int是4个字节。(以下unsigned char将用UINT8代替,int用UINT32代替)

  1. UINT32→UINT8
    ① 这部分是将一个UINT32型数转化为UINT8数组
    ② <<和>>是位操作符,在C语言中没有二进制的表示方式,但计算机本来只有0和1两个数字,也就是二进制,所以我的理解是,一旦涉及到计算机操作,比如位操作,数值将自动转化成二进制,不需要再用语言进行描述表示。
    ③ 4字节的UINT32型数值放到单个元素1字节的UINT8数组中,可以理解为“4字节→4×1字节”,即将4字节的UINT32型拆分成4×1个字节,分别存到UINT8数组的四个元素中。
    ④ UINT32为4字节=32位,因此1个字节=8位,采用大端序进行存储,即高位存在低地址。剧透以下,1246对应的二进制是10011011110,把所有0都补全的话是00000000000000000000010011011110,但通常前面多余的0是不加的,这里写上是为了下面的图更清晰一些。

    ⑤ 大端序就是把高位存储到低地址,即把最左边的“0000 0000”存储在msg[0]里面,采用位操作提取UINT32中的这个字节,如图,src向右位移24位,蓝色为要提取的值,绿色为位移后自动添加的值,红色为位移后被舍弃的值,这么看其实最后得到的值依然是4字节,但其实由于位移24位之后,新添加的(绿色)的值肯定为0,可以舍弃,通过强制类型转换(UINT8)(src >> 24)可以让位移后的四字节只保留最后的一个字节(蓝色)。

    ⑥ 高位低字节的提取也是一样的道理,由于最后结果依旧为0,就不演示了。
    ⑦ 第三位的提取再来演示一下,蓝色为需要提取的字节,绿色为新增,红色为舍弃,最终,将二进制数“100”存在msg[2]中。

    ⑧ 最后一位不需要位移就可以提取。
    ⑨ 这里讲一下(UINT8)((src & 0xff000000) >> 24)中的“& 0xff000000”,这个操作是“按位与”,是为了将除要提取的字节之外其他的字节都置0,但由于在这条语句中不管是提取字节之前还是之后,要么删除要么增0,因此这个操作看似无用,但在其他特殊的时候,是有必要的。
    ⑩ 最终在msg中存储的数据分别为,msg[0]='0’,msg[1]='0’,msg[2]='4’,msg[3]='de’,数据以16进制的形式存储,就此实现UINT32→UINT8,即int→unsigned char的转换。

  2. UINT8→UINT32
    ① 这部分就相对简单一些了,就是把存在msg中的数拿出来乘以量级,再相加,这里乘量级同样是通过为操作来实现的。
    ② 一个图解释转换过程,依然采用大端序,高位存储在低地址。

就此两种转换都已经完成,当然只是按照我自己的理解写的,我也不确定这种理解方式是不是准确,如果有更通俗或者准确的理解再来更新,今天没写多少代码,但写这个过程就花了接近两个小时。以后需要加深对程序、对计算机的理解。

(0)

相关推荐