欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C/C++?判斷計(jì)算機(jī)存儲(chǔ)器字節(jié)序(端序)的幾種方式

 更新時(shí)間:2024年10月05日 08:59:22   作者:escwqa  
字節(jié)序是計(jì)算機(jī)存儲(chǔ)數(shù)據(jù)的格式,主存儲(chǔ)器(主存)的字節(jié)序?qū)Τ绦虻囊浦残院图嫒菪灾陵P(guān)重要,利用聯(lián)合體、指針、位移和掩碼等方法可以檢測(cè)和處理字節(jié)序問(wèn)題,對(duì)于內(nèi)存數(shù)據(jù)操作重要,也關(guān)系到跨平臺(tái)和網(wǎng)絡(luò)通信的數(shù)據(jù)處理

字節(jié)序分為存儲(chǔ)器字節(jié)序和網(wǎng)絡(luò)字節(jié)序(通常采用大端),這里主要討論的是主存儲(chǔ)器字節(jié)序。

主存是存儲(chǔ)器中的一種,為什么只討論主存?因?yàn)榫帉戇\(yùn)行在現(xiàn)代主流操作系統(tǒng)上的程序,是沒(méi)有 I/O 權(quán)限的。

主存字節(jié)序

所謂字節(jié)序就是字節(jié)排列的順序,拿主存來(lái)說(shuō)就是如果低字節(jié)存放在低地址處,就是低端字節(jié)序(小端),反之為高端字節(jié)序(大端)。拿 0x1234567 來(lái)說(shuō):

判斷字節(jié)序

通過(guò)指針

既然字節(jié)序就是字節(jié)的排列順序,那么我們把至少 2 字節(jié)的字節(jié)序列存放到主存中,如果能獲取該數(shù)據(jù)的最低或最高地址的 1 字節(jié)數(shù)據(jù),不就知道字節(jié)序了嗎?對(duì)應(yīng) C/C++ 來(lái)說(shuō)就是指針。

#include <stdio.h>

int main(void)
{
    unsigned int i = 1;
    char *ch_ptr = (char*)&i;  // 創(chuàng)建一個(gè)指向 i 的字符(字節(jié))指針

    if (*ch_ptr)
    {
        printf("Little-Endian\n");  // 如果 *ch_ptr 為 1,表示最低位字節(jié)為 1,為小端
    }
    else
    {
        printf("Big-Endian\n");     // 否則為大端
    }

    return 0;
}

為了保障可移植性,我這里用的是 unsigned int i,以確保每個(gè)平臺(tái)都至少 2 個(gè)字節(jié)。其它數(shù)據(jù)類型甚至是數(shù)組都是可以的,沒(méi)有本質(zhì)的區(qū)別,都是在主存中存儲(chǔ)相應(yīng)數(shù)量的字節(jié)序列。

使用聯(lián)合體(Union)

聯(lián)合體允許在相同的內(nèi)存位置存儲(chǔ)不同的數(shù)據(jù)類型,并且可以通過(guò)不同的成員來(lái)檢視同一塊內(nèi)存區(qū)域。利用該特性,我們可以在聯(lián)合體中定義兩個(gè)成員,其中一個(gè)成員確保為 1 字節(jié)(當(dāng)然,也可以定義成數(shù)組,然后取數(shù)組中的第一個(gè)元素),而另一個(gè)成員則確保每個(gè)平臺(tái)都至少為 2 字節(jié)。

#include <stdio.h>

typedef union
{
	unsigned int i;
	char byte;
} ByteOrder;

int main(void)
{
    ByteOrder order;
    order.i = 1;  // 將整數(shù) 1 存儲(chǔ)到聯(lián)合體中

    if (order.byte)
	{
        printf("Little-Endian\n");  // 如果最低位字節(jié)存儲(chǔ)的是 1,則為小端
    }
	else
	{
        printf("Big-Endian\n");     // 否則為大端
    }

    return 0;
}

如前所述,char byte 可以改為 char ch_arr[sizeof(unsigned int)] 形式的數(shù)組,然后需要將 order.byte 改為 order.ch_arr[0]。

這兩種方法本質(zhì)上是一樣的,都是通過(guò)判斷數(shù)據(jù)的低位字節(jié)在內(nèi)存中的位置來(lái)判斷字節(jié)序。可以根據(jù)實(shí)際情況選擇其中一種方法來(lái)使用。

除了使用聯(lián)合體和指針外,還有一些其它方法可以檢測(cè)字節(jié)序。

位移和掩碼

這種方法利用位操作(位移和掩碼)來(lái)檢測(cè)字節(jié)序。它不依賴于聯(lián)合體,也不需要指針操作,而是直接通過(guò)數(shù)值操作來(lái)判斷:

#include <stdio.h>

int main(void)
{
	unsigned int i = 1; // 只有最低位是 1 的整數(shù)

    if ( (i >> 0) & 1 ) // 將 i 右移 0 位后與 1 進(jìn)行與操作
	{
        printf("Little-Endian\n");
    }
	else
	{
        printf("Big-Endian\n");
    }

    return 0;
}

這種方法簡(jiǎn)單明了,通過(guò)將整數(shù) 1(其二進(jìn)制形式在小端中為 01 00 00 00,在大端中為 00 00 00 01)的最低位(最右邊的位)與 1 進(jìn)行與操作。如果結(jié)果為 1,那么說(shuō)明機(jī)器是小端字節(jié)序。

這種方法的好處是代碼簡(jiǎn)單,且沒(méi)有使用額外的內(nèi)存(如聯(lián)合體或指針)。它直接通過(guò)整型數(shù)值本身的操作來(lái)確定字節(jié)序。

性能對(duì)比

聯(lián)合體:這種方法涉及訪問(wèn)聯(lián)合體的不同成員。聯(lián)合體方法的優(yōu)點(diǎn)是直觀易懂,但訪問(wèn)聯(lián)合體成員可能導(dǎo)致微小的性能開(kāi)銷,尤其是在編譯器優(yōu)化不足的情況下。

指針:這種方法涉及將一個(gè)整數(shù)的地址轉(zhuǎn)換為字符指針,然后檢查具體的字節(jié)。這種方法可能稍微快一點(diǎn),因?yàn)樗苯硬僮鲀?nèi)存,沒(méi)有額外的抽象層。然而,這通常是微不足道的。

位移和掩碼:此方法使用位操作來(lái)檢查字節(jié)序。位操作效率非常高,因?yàn)樗侵苯釉诩拇嫫骷?jí)別上進(jìn)行的,沒(méi)有內(nèi)存訪問(wèn)的開(kāi)銷。

在大多數(shù)實(shí)際應(yīng)用中,字節(jié)序的檢查通常只在程序啟動(dòng)或初始化階段進(jìn)行一次,因此這里的性能差異幾乎可以忽略不計(jì)。即便如此,從純粹理論和微優(yōu)化的角度來(lái)看,位移和掩碼方法可能是最快的,因?yàn)樗苊饬巳魏蝺?nèi)存訪問(wèn),直接在處理器中完成所有操作。

然而,選擇哪種方法應(yīng)該基于代碼的可讀性、可維護(hù)性以及平臺(tái)兼容性,而不僅僅是微小的性能差異。在大多數(shù)情況下,清晰和正確的代碼要比微小的性能提升更加重要。

其它方法

除了前面提到的 3 種常見(jiàn)方法,還可以使用一些更具體或高級(jí)的技術(shù)來(lái)檢測(cè)或處理字節(jié)序問(wèn)題,尤其是在涉及到跨平臺(tái)兼容性或網(wǎng)絡(luò)通信時(shí)。

標(biāo)準(zhǔn)庫(kù)函數(shù)

在某些編程環(huán)境中,標(biāo)準(zhǔn)庫(kù)提供了函數(shù)來(lái)處理字節(jié)序問(wèn)題。例如,在 C 語(yǔ)言中,網(wǎng)絡(luò)編程常用的庫(kù)如 <arpa/inet.h> 提供了 htonl()ntohl() 函數(shù),用于將主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序,或反之。這些函數(shù)自動(dòng)考慮了底層平臺(tái)的字節(jié)序:

#include <stdio.h>
#include <arpa/inet.h>

int main(void)
{
    unsigned int x = 0x12345678;
    unsigned int y = htonl(x);  // 主機(jī)到網(wǎng)絡(luò)字節(jié)序

    if (y == x)
	{
        printf("Big-Endian\n");
    }
	else
	{
        printf("Little-Endian\n");
    }

    return 0;
}

該方法不僅能判斷字節(jié)序,還能在需要的時(shí)候轉(zhuǎn)換字節(jié)序,非常適合網(wǎng)絡(luò)通信中的數(shù)據(jù)交換。

編譯器特定的預(yù)定義宏

一些編譯器提供預(yù)定義的宏來(lái)指示目標(biāo)平臺(tái)的字節(jié)序。例如,GCC 和一些其他編譯器可能定義了特定的宏,可以在編譯時(shí)判斷字節(jié)序。這種方法在編譯時(shí)就確定了字節(jié)序,無(wú)需運(yùn)行時(shí)檢測(cè)。

GCC 和 Clang 編譯器

GCC 和 Clang 通常不直接提供檢測(cè)字節(jié)序的宏,但你可以根據(jù)平臺(tái)或者架構(gòu)特定的預(yù)定義宏來(lái)推斷字節(jié)序。例如,你可以檢查是否定義了特定于某個(gè)架構(gòu)的宏:

#include <stdio.h>

int main(void)
{
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    printf("Little-endian\n");
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    printf("Big-endian\n");
#else
    printf("Unknown byte order\n");
#endif

	return 0;
}

這里使用了 GCC 和 Clang 編譯器提供的 __BYTE_ORDER__ 宏以及相關(guān)的 __ORDER_LITTLE_ENDIAN____ORDER_BIG_ENDIAN__ 宏來(lái)確定字節(jié)序。

MSVC 編譯器

MSVC 編譯器沒(méi)有直接提供檢測(cè)字節(jié)序的宏,因?yàn)?Windows 平臺(tái)通常是小端字節(jié)序。如果你在使用 Visual Studio 且需要編寫可移植的代碼,可能需要自行定義這些宏或者使用其他方法來(lái)確定字節(jié)序。

跨平臺(tái)編譯

如果項(xiàng)目涉及不同的編譯器和平臺(tái),就需要組合多種方法來(lái)使用,確保在這些宏未定義的情況下中也能夠處理。

#include <stdio.h>

int main(void)
{
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    printf("Little-endian\n");
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    printf("Big-endian\n");
#elif defined(_BIG_ENDIAN)
    printf("Big-endian\n");
#elif defined(_LITTLE_ENDIAN)
    printf("Little-endian\n");
#else
    printf("Byte order unknown or assuming default (e.g., little-endian)\n");
#endif

	return 0;
}

常見(jiàn) CPU 的字節(jié)序

大端字節(jié)序:IBM、Sun、PowerPC。

小端字節(jié)序:x86、DEC 。

ARM 體系的 CPU 則大小端字節(jié)序通吃,具體用哪類字節(jié)序由硬件選擇。

到此這篇關(guān)于C/C++ 判斷計(jì)算機(jī)存儲(chǔ)器字節(jié)序(端序)的幾種方式 的文章就介紹到這了,更多相關(guān)C/C++ 字節(jié)序與數(shù)據(jù)存儲(chǔ)及通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言簡(jiǎn)析指針用途

    C語(yǔ)言簡(jiǎn)析指針用途

    C語(yǔ)言這門課程在計(jì)算機(jī)的基礎(chǔ)教學(xué)中一直占有比較重要的地位,然而要想突破C語(yǔ)言的學(xué)習(xí),對(duì)指針的掌握是非常重要的,本文將具體針對(duì)指針的基礎(chǔ)做詳盡的介紹
    2022-07-07
  • VC小技巧匯總之控件技巧

    VC小技巧匯總之控件技巧

    這篇文章主要介紹了VC小技巧匯總之控件技巧,對(duì)于VC的開(kāi)發(fā)很有借鑒價(jià)值,需要的朋友可以參考下
    2014-07-07
  • C語(yǔ)言詳細(xì)分析講解關(guān)鍵字enum與sizeof及typedef的用法

    C語(yǔ)言詳細(xì)分析講解關(guān)鍵字enum與sizeof及typedef的用法

    在?C?語(yǔ)言中經(jīng)常會(huì)見(jiàn)到?enum、sizeof、typedef,那么我們今天就來(lái)講解下它們?nèi)齻€(gè),enum是C語(yǔ)言中的一種自定義類型,它是一種枚舉類型,sizeof是編譯器的內(nèi)置指示符,用于計(jì)算類型或變量所占內(nèi)存打小,typedef用于給一個(gè)已經(jīng)存在的數(shù)據(jù)類型重命名,本質(zhì)上不能產(chǎn)生新的類型
    2022-04-04
  • C++中for auto的用法及說(shuō)明

    C++中for auto的用法及說(shuō)明

    這篇文章主要介紹了C++中for auto的用法及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 詳解C語(yǔ)言數(shù)組越界及其避免方法

    詳解C語(yǔ)言數(shù)組越界及其避免方法

    這篇文章主要介紹了詳解C語(yǔ)言數(shù)組越界及其避免方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • C++解析ini文件的實(shí)現(xiàn)方法

    C++解析ini文件的實(shí)現(xiàn)方法

    在C++編程中,有時(shí)我們需要處理配置文件來(lái)存儲(chǔ)應(yīng)用程序的設(shè)置和參數(shù),而INI文件是一種常見(jiàn)的選擇,這篇文章主要給大家介紹了關(guān)于C++解析ini文件的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2024-08-08
  • C++17中的std::optional的具體使用

    C++17中的std::optional的具體使用

    這篇文章主要介紹了C++17中的std::optional的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • C++中delete指針后最好將其置空的操作方法

    C++中delete指針后最好將其置空的操作方法

    C++編程中,當(dāng)你使用delete運(yùn)算符釋放指針?biāo)赶虻膬?nèi)存后,通常將該指針置空,如果一個(gè)指針在被刪除后沒(méi)有置空,而你在代碼的其他部分再次嘗試刪除同一個(gè)指針,可能會(huì)導(dǎo)致程序崩潰或產(chǎn)生未定義行為,本文介紹C++中delete指針后最好將其置空的操作方法,感興趣的朋友一起看看吧
    2024-06-06
  • C++第三方庫(kù)jsoncpp超詳細(xì)講解

    C++第三方庫(kù)jsoncpp超詳細(xì)講解

    這篇文章主要介紹了C++第三方庫(kù)jsoncpp的相關(guān)資料,JSONcpp是一個(gè)在C++中用于處理JSON數(shù)據(jù)的庫(kù),支持JSON格式的序列化和反序列化,通過(guò)JSONcpp,可以輕松地將數(shù)據(jù)對(duì)象組織成JSON格式的字符串,需要的朋友可以參考下
    2024-10-10
  • char str[] 與 char *str的區(qū)別詳細(xì)解析

    char str[] 與 char *str的區(qū)別詳細(xì)解析

    以下是對(duì)char str[]與char *str的區(qū)別進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-09-09

最新評(píng)論