概念
go默认使用Unicode字符集,同时使用utf-8作为编码方式
go里面没有字符类型(char),而是使用byte(uint8)和rune(int32)来代表字符。
我们声明一个字符时,默认是rune类型,除非特别定义。 一个string变量既可以被拆分为字符,也可以被拆分为字节;前者使用rune[]切片表示,后者使用byte[]切片表示
一个rune值就是代表一个字符,在输入输出中经常看到类似’\U0001F3A8’,’\u2665’的就是一个rune字符(unicode字符),其中的每位都是一个16进制数
var a = 'A' // rune type
var b byte = 'a' // byte type
c:= byte('b') // byte type
本质上,byte其实都是整型类型,其中byte是uint8的别称,rune是int32的别称。例如一个byte类型的字符'a'其实是整型数字97,对应ASCII码的字符a。
var a = 'a'
var b byte = 'a'
fmt.Printf("%T, %v", a, a) // int32, 97
fmt.Printf("%T, %v", b, b) // uint8, 97
byte类型和rune类型使用编码方式不同,其中byte是ASCII编码字符,rune是utf-8字符。
string
字符串可以为空,但不能为nil;
字符串的值不能修改,只能替换;
修改字符串时需要重新分配一次内存,之前分配的内存由gc回收(因此字符串比较低效)
[]byte字符串
[]byte字符串类型适用于字符串的拼接:
byte 字符
[]byte 字符串
[][]byte字符串数组
b1 := byte('a') // 字符
b2 := []byte("A") // 字符串
b3 := []byte{'a', 'b', 'c'} // 字符串
fmt.Printf("b1 = %c\n", b1)
fmt.Printf("b2 = %c\n", b2)
fmt.Printf("b3 = %s\n", b3)
s1 := []byte("Hello") // 字符串
s2 := []byte("World") // 字符串
s3 := [][]byte{s1, s2} // 字符串数组
s4 := bytes.Join(s3, []byte(","))
s5 := []byte{}
s5 = bytes.Join(s3, []byte("--"))
s6 := [][]byte{[]byte("foo"), []byte("bar"), []byte("baz")}
fmt.Printf("s1 = %s\n", s1)
fmt.Printf("s2 = %s\n", s2)
fmt.Printf("s3 = %s\n", s3)
fmt.Printf("s4 = %s\n", s4)
fmt.Printf("s5 = %s\n", s5)
fmt.Printf("%s\n", bytes.Join(s6, []byte(", ")))
b1 = a
b2 = [A]
b3 = abc
s1 = Hello
s2 = World
s3 = [Hello World]
s4 = Hello,World
s5 = Hello--World
foo, bar, baz
String和[]byte转换及使用场景
转换
// string to []byte
s1 := "hello"
b := []byte(s1)
// []byte to string
s2 := string(b)
使用场景
需要用做map的key时,用string,因为string可以直接比较,[]byte不可以
如果需要用nil来表示额外的含义,用[]byte,因为string不能取nil值,[]byte可以
————————————————
版权声明:本文为CSDN博主「AXIMI」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/AXIMI/article/details/120379225
C语言中什么叫做高八位和低八位啊?
高八位和低八位:内存里,一个单元是一个字节,也就是8位。如果是16位的指令,就是同时操作连续的2个内存地址,将这连续的2个内存地址当成一个单位,所以就有高8位和低8位之分。
由于计算机仅识别二进制描述的数字,所以对一个内存地址,也就是8位二进制,如:0000 0001,0000就是高四位,0001就是低四位。
当然2个内存地址,就是16位二进制,也就是:0000 0001 0000 0002。0000 0001 就是高八位,0000 0002就是低八位。
每个八位中又分成高低四位。如:1010 0001 1111 0101,换算成16进制就是:1010–10(10进制)—A(16进制),0001–1(10进制)—1(16进制)所以他的高八位就是A1,同样它的低八位就是F5。
扩展资料:
如何在C语言中的ascII码表里查找高四位、低四位:
ascii码在C语言中用char型存储,一个char占一个字节,即8位。
当写成二进制表达形式时,就是8个0或者1的数字,这8个数字中,左边四个称为高四位,右边四个称为低四位。
所以在查ascii码表时,需要:
1、把要查的值,转成二进制值;
2、得到高四位值,及低四位值;
3、根据高四位值查表,找到所在列;
4、根据低四位值查表,找到所在行;
5、所在行列的交叉格,就是要查找的字符。
主机字节序
主机字节序模式有两种,大端数据模式和小端数据模式,在网络编程中应注意这两者的区别,以保证数据处理的正确性;例如网络的数据是以大端数据模式进行交互,而我们的主机大多数以小端模式处理,如果不转换,数据会混乱 参考 ;一般来说,两个主机在网络通信需要经过如下转换过程:主机字节序 —> 网络字节序 -> 主机字节序
大端小端区别
大端模式:Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端
低地址 --------------------> 高地址
高位字节 地位字节
小端模式:Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端
低地址 --------------------> 高地址
低位字节 高位字节
什么是高位字节和低位字节
例如在32位系统中,357转换成二级制为:00000000 00000000 00000001 01100101,其中
00000001 | 01100101
高位字节 低位字节
int和byte转换
在go语言中,byte其实是uint8的别名,byte 和 uint8 之间可以直接进行互转。目前来只能将0~255范围的int转成byte。因为超出这个范围,go在转换的时候,就会把多出来数据扔掉;如果需要将int32转成byte类型,我们只需要一个长度为4的[]byte数组就可以了
大端模式下
func f2() {
var v2 uint32
var b2 [4]byte
v2 = 257
// 将 257转成二进制就是
// | 00000000 | 00000000 | 00000001 | 00000001 |
// | b2[0] | b2[1] | b2[2] | b2[3] | // 这里表示b2数组每个下标里面存放的值
// 这里直接使用将uint32强转成uint8
// | 00000000 0000000 00000001 | 00000001 直接转成uint8后等于 1
// |---这部分go在强转的时候扔掉---|
b2[3] = uint8(v2)
// | 00000000 | 00000000 | 00000001 | 00000001 | 右移8位 转成uint8后等于 1
// 下面是右移后的数据
// | | 00000000 | 00000000 | 00000001 |
b2[2] = uint8(v2 >> 8)
// | 00000000 | 00000000 | 00000001 | 00000001 | 右移16位 转成uint8后等于 0
// 下面是右移后的数据
// | | | 00000000 | 00000000 |
b2[1] = uint8(v2 >> 16)
// | 00000000 | 00000000 | 00000001 | 00000001 | 右移24位 转成uint8后等于 0
// 下面是右移后的数据
// | | | | 00000000 |
b2[0] = uint8(v2 >> 24)
fmt.Printf("%+v\n", b2)
// 所以最终将uint32转成[]byte数组输出为
// [0 0 1 1]
}
小端模式下
在上面我们讲过,小端刚好和大端相反的,所以在转成小端模式的时候,只要将[]byte数组的下标首尾对换一下位置就可以了
func f3() {
var v3 uint32
var b3 [4]byte
v3 = 257
// 将 256转成二进制就是
// | 00000000 | 00000000 | 00000001 | 00000001 |
// | b3[0] | b3[1] | b3[2] | [3] | // 这里表示b3数组每个下标里面存放的值
// 这里直接使用将uint32l强转成uint8
// | 00000000 0000000 00000001 | 00000001 直接转成uint8后等于 1
// |---这部分go在强转的时候扔掉---|
b3[0] = uint8(v3)
// | 00000000 | 00000000 | 00000001 | 00000001 | 右移8位 转成uint8后等于 1
// 下面是右移后的数据
// | | 00000000 | 00000000 | 00000001 |
b3[1] = uint8(v3 >> 8)
// | 00000000 | 00000000 | 00000001 | 00000001 | 右移16位 转成uint8后等于 0
// 下面是右移后的数据
// | | | 00000000 | 00000000 |
b3[2] = uint8(v3 >> 16)
// | 00000000 | 00000000 | 00000001 | 00000001 | 右移24位 转成uint8后等于 0
// 下面是右移后的数据
// | | | | 00000000 |
b3[3] = uint8(v3 >> 24)
fmt.Printf("%+v\n", b3)
// 所以最终将uint32转成[]byte数组输出为
// [1 1 0 0 ]
}
go转换demo
案例1
//整形转换成字节
func IntToBytes(n int) []byte {
x := int32(n)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, x)
return bytesBuffer.Bytes()
}
//字节转换成整形
func BytesToInt(b []byte) int {
bytesBuffer := bytes.NewBuffer(b)
var x int32
binary.Read(bytesBuffer, binary.BigEndian, &x)
return int(x)
}
案例2
arg := uint32(115)
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, arg)
源码
func (bigEndian) PutUint32(b []byte, v uint32) {
_ = b[3] // early bounds check to guarantee safety of writes below
b[0] = byte(v >> 24)
b[1] = byte(v >> 16)
b[2] = byte(v >> 8)
b[3] = byte(v)
}
相关面试题
1.mysql 中int(11)最大最小存储多少
| tinyint | smallint | mediumint | int | bigint |
| 1 | 2 | 3 | 4 | 8 | 占用字节
1字节(Byte)占8个位(bit),1个位表示一个二进制的0或者1,
1个字节能表示最大的整数是255,怎么来的?
1个字节就是8个二进制的1 “11111111” 转换成十进制就是255
1*2^7+1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+1*2^1+1*2^0=255
int 占用4个字节 1个字节是8个位(bit) 即等于32个位(bit)
有符号 int 取值范围 等于int8 的取值范围 详见下面附属表2.取值范围
-2^31 (-2,147,483,648) 到 2^31 - 1 (2,147,483,647)
无符号 int 取值范围 等于uint8 的取值范围 详见下面附属表2.取值范围
0 到 (2^32) - 1 (4,294,967,295)
tinyint | smallint | mediumint | int | bigint 计算一样参考
关于int(11)中的(11)是mysql 中选择是否填充时使用
当设置填充是假设存储值1 表中则显示为: 00000000001
当不设置填充是假设存储值1 表中则显示为: 1
扩展资料
int类型, 占用字节数为4byte, 学过计算机原理的同学应该知道,字节(byte)并非是计算机存储的最小单位,
还有比字节(byte)更小的单位,也就是位(bit),一个位就代表一个0或1; 8个位组成一个字节;一般字节用大写B来表示byte,位用小写b来表示bit。
附属表1.ASCII码表
附属表2.取值范围