字節序的含義:大於一個字節類型的數據在內存中的存放順序。比如short 或者int在不同的字節序存儲結果是不一樣的。
大字節序(Big-Endian):高位字節排放在內存的低地址端,低位字節排放在內存的高地址端
小字節序(Little-Endian):低位字節排放在內存的低地址端,高位字節排放在內存的高地址端
通過一個簡單的程序來判定該系統是大字節序還是小字節序。
#include <iostream>
int main(){
int number = 1;
if(*(char *)&number)
std::cout<<"Little-endian!\n";
else
std::cout<<"Big-endian!\n";
return 0;
}
該段代碼的原理很簡單。int類型的1,在小字節序下最低位爲1,在大字節序下,最高位爲1。所以可以通過判斷最低位是否爲0來確定該機器的字節序是什麼。
經測試,在Windows,MacOSX,Linux等基於x86的機器上面測試,都是小字節序。
在各種常見編碼(GBK,UTF-8,Unicode)中,只有Unicode會牽扯到字節序這個概念,因爲UCS-2是用short int存儲,UCS-4是用int存儲。
我來用下面這段代碼檢驗一下通過iconv工具做編碼轉化在不同的機器上的效果。
int main(int argc , char ** argv)
{
iconv_t conveter = iconv_open("UCS-2","GB18030");
if(conveter== iconv_t(-1)){
std::cout<<"encode convert not supported!"<<std::endl;
if(errno==EINVAL)
std::cout<<"einval"<<std::endl;
return -1;
}
else{
//std::cout<<"ok!"<<std::endl;
}
size_t insize;
char input[10] = "abcdefg";
char * inin = input;
insize=strlen(input);
//std::cout<<"input is: "<<input<<std::endl;
size_t outsize = insize * 5+1;
char *output = new char[outsize];
char *output_old = output;
memset(output,0,outsize);
size_t ret = iconv(conveter,&inin,&insize,&output_old,&outsize);
if(ret==(size_t)-1){
std::cout<<"converting failed"<<std::endl;
return -1;
}
std::ofstream of;
of.open("yy.txt", std::ios::binary);
of.write(output, outsize);
of.close();
std::cout << output << std::endl;
std::cout << "outsize=" << outsize << std::endl;
delete[] output;
iconv_close(conveter);
return 0;
}
例子很簡單,將gbk編碼的字符串變成unicode編碼,看轉化後的效果是否跟機器的字節序保持一致。經測試結果發現在MacOSX和Linux下面結果有不同。Linux 的結果是正常的,
0000000: 6100 6200 6300 6400 0000 0000 00 a.b.c.d……
但是在OSX下面的結果卻是這樣:
0000000: 0061 0062 0063 0064 0000 0000 00 .a.b.c.d…..
爲什麼會在兩個平臺如此,具體原因沒有深究。但是這種表現會影響Mac下面的轉化結果。在iconv時顯示的指明到底是UCS-2LE還是UCS-2BE,這樣在各個平臺的處理結果是符合預期的,修改這麼一句:
iconv_t conveter = iconv_open("UCS-2LE","GB18030");