![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5yY3EmYkNjMmVDN0MTOjNTNwkjMmBDO2QWZyY2N3QmMz8CXxMzLcdDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL2M3Lc9CX6MHc0RHaiojIsJye.png)
-------------------------
學了這麼多年C語言、C++、VC、MFC,但卻從來沒有認真研究過各種資料類型在記憶體中是如何存儲的。感覺自己一直在弄的都是皮毛,沒有觸及真正核心的東西。直到昨天,重新翻看譚浩強老師經典的《C程式設計(第三版)》,在“第十四章 常見錯誤和程式調試”中有一個例子是這樣的:
1 int a=3;
2 float b=4.5;
3 printf("%f %d",a,b);
輸出的結果是這樣的:
為什麼會是這樣的結果呢?讓我們看一看a和b在記憶體中的存儲方式吧?
int 和 long 一樣,按 2 的補碼、低位位元組在前的形式存儲于 4 個位元組中;
float 按 IEEE 754 單精度數的形式存儲于 4 個位元組中;
double 按 IEEE 754 雙精度數的形式存儲于 8 個位元組中。
a是int型的,在記憶體中占4個位元組,在記憶體中的存儲方式:
位址:0x0012ff7c 0x0012ff7d 0x0012ff7e 0x0012ff7f
數值: 03 00 00 00
b是float型的,在記憶體中占4個位元組,在記憶體中的存儲方式:
位址:0x0012ff70 0x0012ff71 0x0012ff72 0x0012ff73
數值: 00 00 90 40
-----------------------------------------------------------------------
package main
import (
"log"
"bytes"
"encoding/binary"
)
//整形轉換成位元組
func IntToBytes(n int) []byte {
x := int32(n)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.LittleEndian, x)
return bytesBuffer.Bytes()
}
func bytes2Int(b []byte) int {
bytesBuffer := bytes.NewBuffer(b)
var tmp uint32
err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
if err != nil {
log.Println("[]byte 2 int err:", err)
return 0
}
return int(tmp)
}
func float64ToByte(f float32) []byte {
var buf bytes.Buffer
err := binary.Write(&buf, binary.BigEndian, f)
if err != nil {
log.Println("binary.Write failed:", err)
}
return buf.Bytes()
}
func main() {
var a int
a = 36928
log.Println(IntToBytes(a))
var b,c,d float32
b =1.251
log.Println(float64ToByte(b))
c = 4.5
log.Println(float64ToByte(c))
log.Println("a:", bytes2Int(float64ToByte(c)))
d = 17.625
log.Printf("%x",float64ToByte(d))
}
c代碼:
C Function to Convert float to byte array
#include <stdio.h>
int main(void) {
int ii;
union {
float a;
unsigned char bytess[4];
int b;
} thing;
thing.a = 4.5;
for (ii=0; ii<4; ii++)
printf ("byte %d is %02x\n", ii, thing.bytess[ii]);
printf("%d\n", thing.b);
return 0;
}
-------------------
主機位元組序
主機位元組序模式有兩種,大端資料模式和小端資料模式,在網絡程式設計中應注意這兩者的差別,以保證資料處理的正确性;例如網絡的資料是以大端資料模式進行互動,而我們的主機大多數以小端模式處理,如果不轉換,資料會混亂 參考 ;一般來說,兩個主機在網絡通信需要經過如下轉換過程:主機位元組序 —> 網絡位元組序 -> 主機位元組序
大端小端差別
大端模式: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數組就可以了
大端模式下
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 27 | |
小端模式下
28 | |