女人荫蒂被添全过程13种图片,亚洲+欧美+在线,欧洲精品无码一区二区三区 ,在厨房拨开内裤进入毛片

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語言中編寫協(xié)議相關(guān)代碼位域的值解析不對勁怎么辦?

FPGA之家 ? 來源:一口Linux ? 作者:一口Linux ? 2021-05-03 09:41 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1. 粉絲問題

自己編寫的一個(gè)協(xié)議相關(guān)代碼,位域的值解析和自己想象的有出入。

48958194-a2d1-11eb-aece-12bb97331649.png

問題

結(jié)構(gòu)體的頭:

48ad9fe0-a2d1-11eb-aece-12bb97331649.png

解析代碼和測試結(jié)果:

497d6054-a2d1-11eb-aece-12bb97331649.png

就是說通過函數(shù)hexdump()解析出的內(nèi)存是十六進(jìn)制是 81 83 20 3B 。..。..

從數(shù)據(jù)幀解析出的

opcode = 0x8

該粉絲不明白為什么解析出的值是0x8。

這個(gè)問題其實(shí)就是位域的問題和字節(jié)序的問題。

測試代碼

廢話不多說,直接寫個(gè)測試代碼

#include 《stdio.h》

//簡化的結(jié)構(gòu)體

struct iphdr {

unsigned char fin:1;

unsigned char rsv:3;

unsigned char opcode:4;

unsigned char mask:1;

unsigned char payload:7;

unsigned char a;

unsigned char b;

};

main()

{

struct iphdr t;

unsigned char *s;

//清空內(nèi)存,防止有亂碼

memset(&t,0,4);

//用指針指向結(jié)構(gòu)體變量t

s = (unsigned char*)&t;

//通過數(shù)組訪問的方式修改內(nèi)存的值,因?yàn)閔exdump解析的值是0x81 83,

//所以0x81必為最低字節(jié)的內(nèi)存的數(shù)據(jù)

s[0] = 0x81;

s[1] = 0x83;

//打印出位域成員的值

printf(“fin:%d rsv:%d opcode:%d mask:%d paylod:%d

”,

t.fin,t.rsv,t.opcode,t.mask,t.payload);

}

執(zhí)行結(jié)果:

fin:1,rsv:0,opcode:8,mask:1 paylod:65

分析:如下圖所示,紫色部分是位域成員對應(yīng)的內(nèi)存中的實(shí)際空間布局,地址從左到右增加第一個(gè)字節(jié)的0x81賦值后,各位域?qū)?yīng)的二進(jìn)制:

fin:1

rsv:0

opcode:1000

mask:1

paylod:1000001

499211a2-a2d1-11eb-aece-12bb97331649.png

如上圖多少,內(nèi)存的第1個(gè)字節(jié)是0x81,第2個(gè)字節(jié)是0x83;

第一個(gè)字節(jié)0x81的最低的bit[0]對應(yīng)fin,bit[3:1]對應(yīng)rsv,bit[7:4]對應(yīng)opcode;第二個(gè)字節(jié)0x83的最低bit[0]對應(yīng)mask,bit[7:1]對應(yīng)payload。

所以結(jié)果顯而易見。

2、什么是位域?

有些信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié), 而只需占幾個(gè)或一個(gè)二進(jìn)制位。

例如在存放一個(gè)開關(guān)量時(shí),只有0和1 兩種狀態(tài), 用一位二進(jìn)位即可。為了節(jié)省存儲(chǔ)空間,并使處理簡便,C語言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為“位域”或“位段”。

所謂“位域”是把一個(gè)字節(jié)中的二進(jìn)位劃分為幾個(gè)不同的區(qū)域,并說明每個(gè)區(qū)域的位數(shù)。

每個(gè)域有一個(gè)域名,允許在程序中按域名進(jìn)行操作。這樣就可以把幾個(gè)不同的對象用一個(gè)字節(jié)的二進(jìn)制位域來表示。一、位域的定義和位域變量的說明位域定義與結(jié)構(gòu)定義相仿,其形式為:

struct 位域結(jié)構(gòu)名

{

位域列表

};

其中位域列表的形式為:

類型說明符 位域名:位域長度

如粉絲所舉的實(shí)例:

struct iphdr {

unsigned char fin:1;

unsigned char rsv:3;

unsigned char opcode:4;

unsigned char mask:1;

unsigned char payload:7;

unsigned char a;

unsigned char b;

};

位域變量的說明與結(jié)構(gòu)變量說明的方式相同。可采用先定義后說明,同時(shí)定義說明或者直接說明這三種方式。例如:

struct bs

{

int a:8;

int b:2;

int c:6;

}data;

說明data為bs變量,共占兩個(gè)字節(jié)。其中位域a占8位,位域b占2位,位域c占6位。對于位域的定義尚有以下幾點(diǎn)說明:

一個(gè)位域必須存儲(chǔ)在同一個(gè)字節(jié)中,不能跨兩個(gè)字節(jié)。

如一個(gè)字節(jié)所剩空間不夠存放另一位域時(shí),應(yīng)從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:

struct bs

{

unsigned a:4

unsigned :0 /空域/

unsigned b:4 /從下一單元開始存放/

unsigned c:4

};

在這個(gè)位域定義中,a占第一字節(jié)的4位,后4位填0表示不使用,b從第二字節(jié)開始,占用4位,c占用4位。

位域可以無位域名,這時(shí)它只用來作填充或調(diào)整位置。無名的位域是不能使用的。例如:

struct k

{

int a:1

int :2 /該2位不能使用/

int b:3

int c:2

};

從以上分析可以看出,位域在本質(zhì)上就是一種結(jié)構(gòu)類型, 不過其成員是按二進(jìn)位分配的。

這是位域操作的表示方法,也就是說后面加上“:1”的意思是這個(gè)成員的大小占所定義類型的1 bit,“:2”占2 bit,依次類推。當(dāng)然大小不能超過所定義類型包含的總bit數(shù)。

一個(gè)bytes(字節(jié))是8個(gè) bit(二進(jìn)制位)。例如你的結(jié)構(gòu)體中定義的類型是u_char,一個(gè)字節(jié),共8個(gè)bit,最大就不能超過8。32位機(jī)下,short是2字節(jié),共16bit,最大就不能超過16,int是4字節(jié),共32bit,最大就不能超過32.依次類推。

位域定義比較省空間。

例如你上面的結(jié)構(gòu),定義的變量類型是u_char,是一字節(jié)類型,即8bit。

fc_subtype占了4bit,fc_type占2bit,fc_protocol_version占2bit,共8bit,正好是一個(gè)字節(jié)。

其他八個(gè)成員,各占1bit,共8bit,正好也是一個(gè)字節(jié)。

因此你的結(jié)構(gòu)的大小如果用sizeof(struct frame_control)計(jì)算,就是2bytes。

3. 如何測試當(dāng)前是大端還是小端?

計(jì)算機(jī)硬件有兩種儲(chǔ)存數(shù)據(jù)的方式:大端字節(jié)序(big endian)和小端字節(jié)序(little endian)。大端字節(jié)序:高位字節(jié)在前,低位字節(jié)在后,這是人類讀寫數(shù)值的方法。小端字節(jié)序:低位字節(jié)在前,高位字節(jié)在后。

0x1234567的大端字節(jié)序和小端字節(jié)序的寫法如下圖。

49b731f8-a2d1-11eb-aece-12bb97331649.png

為什么會(huì)有小端字節(jié)序?

答案是,計(jì)算機(jī)電路先處理低位字節(jié),效率比較高,因?yàn)橛?jì)算都是從低位開始的。所以,計(jì)算機(jī)的內(nèi)部處理都是小端字節(jié)序。

但是,人類還是習(xí)慣讀寫大端字節(jié)序。所以,除了計(jì)算機(jī)的內(nèi)部處理,其他的場合幾乎都是大端字節(jié)序,比如網(wǎng)絡(luò)傳輸和文件儲(chǔ)存。

計(jì)算機(jī)處理字節(jié)序的時(shí)候,不知道什么是高位字節(jié),什么是低位字節(jié)。它只知道按順序讀取字節(jié),先讀第一個(gè)字節(jié),再讀第二個(gè)字節(jié)。

如果是大端字節(jié)序,先讀到的就是高位字節(jié),后讀到的就是低位字節(jié)。小端字節(jié)序正好相反。

理解這一點(diǎn),才能理解計(jì)算機(jī)如何處理字節(jié)序。

處理器讀取外部數(shù)據(jù)的時(shí)候,必須知道數(shù)據(jù)的字節(jié)序,將其轉(zhuǎn)成正確的值。然后,就正常使用這個(gè)值,完全不用再考慮字節(jié)序。

即使是向外部設(shè)備寫入數(shù)據(jù),也不用考慮字節(jié)序,正常寫入一個(gè)值即可。外部設(shè)備會(huì)自己處理字節(jié)序的問題。

實(shí)例

仍然用上面的例子,但是做如下修改

#include 《stdio.h》

struct iphdr {

unsigned char fin:1;

unsigned char rsv:3;

unsigned char opcode:4;

unsigned char mask:1;

unsigned char payload:7;

};

main()

{

struct iphdr t;

unsigned short *s;

memset(&t,0,2);

s = (unsigned char *)&t;

//注意,直接賦值0x8183,因?yàn)樵摮A勘厝缓椭鳈C(jī)字節(jié)序一致,

//小端:83給低字節(jié),

//大端:81給低字節(jié)

*s = 0x8183;

printf(“fin:%d rsv:%d opcode:%d mask:%d paylod:%d

”,

t.fin,t.rsv,t.opcode,t.mask,t.payload);

}

執(zhí)行結(jié)果:

fin:1 rsv:1 opcode:8 mask:1 paylod:64

由結(jié)果可知,收到的0x8183這個(gè)值與對應(yīng)的的二進(jìn)制關(guān)系:

fin:1

rsv:001

opcode:1000

mask:1

paylod:1000000

49dff822-a2d1-11eb-aece-12bb97331649.png

如上圖多少,內(nèi)存的第1個(gè)字節(jié)是0x83,第2個(gè)字節(jié)是0x81【和前面的例子不一樣了,因?yàn)槲覀兪侵苯淤x值0x8183,而該常數(shù)是小字節(jié)序,所以低字節(jié)是0x83】;

可見:

低字節(jié)83給了 fin+rsv+opcode

所以,這說明了一口君的ubuntu是小端字節(jié)序。

4. 拓展例子

繼續(xù)將結(jié)構(gòu)體做如下修改,當(dāng)位域成員大小加一起不夠一個(gè)整字節(jié)的時(shí)候,驗(yàn)證各成員在內(nèi)存中的布局。

#include 《stdio.h》

struct iphdr {

unsigned char fin:1;

unsigned char opcode:4;

unsigned char a;

unsigned char b;

};

main()

{

struct iphdr t;

unsigned char *s;

memset(&t,0,2);

s = (unsigned short *)&t;

t.fin = 1;

t.opcode = 0xf;

printf(“%x

”,s[0]);

}

49e9f476-a2d1-11eb-aece-12bb97331649.png

fin:1

opcode:1111

內(nèi)存中形式如下:

4a020f2a-a2d1-11eb-aece-12bb97331649.png

如果修改fin的值為0:

t.fin = 0;

執(zhí)行結(jié)果如下:

4a0ac91c-a2d1-11eb-aece-12bb97331649.png

fin:0

opcode:1111

內(nèi)存中形式如下:

4a1de466-a2d1-11eb-aece-12bb97331649.png

5. 總結(jié)

大家遇到類似問題的時(shí)候,一定要寫一些實(shí)例去驗(yàn)證,對于初學(xué)者來說,建議多參考上述實(shí)例。

原文標(biāo)題:【問答21】C語言:位域和字節(jié)序

文章出處:【微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7631

    瀏覽量

    141049
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4895

    瀏覽量

    70482

原文標(biāo)題:【問答21】C語言:位域和字節(jié)序

文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    深入理解C語言C語言循環(huán)控制

    改變程序的執(zhí)行流程,使代碼更加靈活和可控。本文將詳細(xì)介紹這些語句的作用及其應(yīng)用場景,并通過示例代碼進(jìn)行說明。Part.1break語句C語言中break語句有兩種
    的頭像 發(fā)表于 04-29 18:49 ?1033次閱讀
    深入理解<b class='flag-5'>C</b><b class='flag-5'>語言</b>:<b class='flag-5'>C</b><b class='flag-5'>語言</b>循環(huán)控制

    C語言中結(jié)構(gòu)體與聯(lián)合體的深度解析:內(nèi)存布局與應(yīng)用場景

    一、基礎(chǔ)概念與核心差異 1.1 結(jié)構(gòu)體(Struct)的本質(zhì) **結(jié)構(gòu)體是C語言中實(shí)現(xiàn)數(shù)據(jù)封裝的基石,其核心特征在于內(nèi)存獨(dú)立性。每個(gè)成員變量在內(nèi)存中按聲明順序依次排列,形成連續(xù)的內(nèi)存塊。以學(xué)生信息為
    發(fā)表于 04-08 09:18

    如何在 樹莓派 上編寫和運(yùn)行 C 語言程序?

    在本教程中,我將討論C編程語言是什么,C編程的用途,以及如何在RaspberryPi上編寫和運(yùn)行C程序。本文的目的是為您介紹在Raspber
    的頭像 發(fā)表于 03-25 09:28 ?504次閱讀
    如何在 樹莓派 上<b class='flag-5'>編寫</b>和運(yùn)行 <b class='flag-5'>C</b> <b class='flag-5'>語言</b>程序?

    EE-62:在C語言中訪問短字內(nèi)存

    電子發(fā)燒友網(wǎng)站提供《EE-62:在C語言中訪問短字內(nèi)存.pdf》資料免費(fèi)下載
    發(fā)表于 01-07 14:02 ?0次下載
    EE-62:在<b class='flag-5'>C</b><b class='flag-5'>語言中</b>訪問短字內(nèi)存

    EE-128:C語言中的DSP:從C調(diào)用匯編類成員函數(shù)

    電子發(fā)燒友網(wǎng)站提供《EE-128:C語言中的DSP:從C調(diào)用匯編類成員函數(shù).pdf》資料免費(fèi)下載
    發(fā)表于 01-07 13:48 ?0次下載
    EE-128:<b class='flag-5'>C</b><b class='flag-5'>語言中</b>的DSP:從<b class='flag-5'>C</b>調(diào)用匯編類成員函數(shù)

    C語言中申請的堆內(nèi)存能不能自動(dòng)釋放

    C語言中申請的堆內(nèi)存能不能自動(dòng)釋放?每次都要手動(dòng) free 太麻煩,也容易忘記。 學(xué)過 C++ 的同學(xué),應(yīng)該首先能想到智能指針。 但是這是C語言
    的頭像 發(fā)表于 11-27 09:33 ?495次閱讀

    PLLATINUMSIM-SW是否有相關(guān)C語言代碼進(jìn)行參考?

    PLLATINUMSIM-SW是否有相關(guān)C語言代碼進(jìn)行參考,以達(dá)到對器件指標(biāo)的準(zhǔn)確評估直觀顯示。
    發(fā)表于 11-11 06:20

    C語言中的socket編程基礎(chǔ)

    數(shù)據(jù) 步驟6:關(guān)閉socket 創(chuàng)建socket 在C語言中,創(chuàng)建socket需要使用socket()函數(shù)。這個(gè)函數(shù)需要兩個(gè)參數(shù):
    的頭像 發(fā)表于 11-01 16:51 ?1154次閱讀

    請問這個(gè)板的原理圖怎么畫?從PCB板倒推原理圖,單層的

    我有自己畫一個(gè),但是總感覺不對勁,想麻煩大家?guī)臀铱匆幌拢兄x
    發(fā)表于 10-08 13:17

    技術(shù)干貨驛站 ▏深入理解C語言:編程高手必備,全方位解析運(yùn)算符的核心技能!

    過程中發(fā)揮著重要作用,還對程序的性能和穩(wěn)定性產(chǎn)生直接影響。繼上一期對C語言常量的深入分析后,本文將進(jìn)一步探討C語言中的常用運(yùn)算符,詳細(xì)解析
    的頭像 發(fā)表于 09-18 15:56 ?739次閱讀
    技術(shù)干貨驛站 ▏深入理解<b class='flag-5'>C</b><b class='flag-5'>語言</b>:編程高手必備,全方位<b class='flag-5'>解析</b>運(yùn)算符的核心技能!

    請問有DS26334芯片的中文資料,和相關(guān)配置的源代碼嗎?以及相關(guān)的傳輸協(xié)議解析

    請問有DS26334芯片的中文資料,和相關(guān)配置的源代碼嗎?以及相關(guān)的傳輸協(xié)議解析
    發(fā)表于 09-04 10:50

    hex文件如何查看原c語言代碼

    直接將 .hex 文件轉(zhuǎn)換回原始的 C 語言代碼是不可能的,因?yàn)?.hex 文件是二進(jìn)制文件,它包含了單片機(jī)程序編譯后的機(jī)器碼,這些機(jī)器碼與原始的 C
    的頭像 發(fā)表于 09-02 10:37 ?4765次閱讀

    技術(shù)干貨驛站 ▏深入理解C語言:掌握常量,讓你的代碼更加穩(wěn)固高效!

    C語言的世界中,常量是一種不可忽視的元素。無論你是在編寫簡單的代碼,還是構(gòu)建復(fù)雜的系統(tǒng),常量都能為你的程序帶來更高的穩(wěn)定性和可靠性。在這篇文章中,我們將深入探討
    的頭像 發(fā)表于 08-29 13:59 ?3494次閱讀
    技術(shù)干貨驛站 ▏深入理解<b class='flag-5'>C</b><b class='flag-5'>語言</b>:掌握常量,讓你的<b class='flag-5'>代碼</b>更加穩(wěn)固高效!

    c語言中從左到右結(jié)合怎么看

    C語言中,操作符的結(jié)合性(Associativity)是指當(dāng)操作符在表達(dá)式中連續(xù)出現(xiàn)時(shí),它們?nèi)绾闻c操作數(shù)結(jié)合的順序。對于大多數(shù)二元操作符(即需要兩個(gè)操作數(shù)的操作符),C語言遵循兩種基
    的頭像 發(fā)表于 08-20 11:42 ?1596次閱讀

    大電流一體成型電感有噪音怎么辦

    電子發(fā)燒友網(wǎng)站提供《大電流一體成型電感有噪音怎么辦.docx》資料免費(fèi)下載
    發(fā)表于 07-30 12:30 ?0次下載
    主站蜘蛛池模板: 崇州市| 浠水县| 永和县| 靖安县| 林甸县| 手游| 景德镇市| 环江| 梓潼县| 鄂托克旗| 十堰市| 天水市| 江永县| 思南县| 宣武区| 凌源市| 孙吴县| 平阳县| 清新县| 资源县| 灌阳县| 德兴市| 宁津县| 黎川县| 延寿县| 高邮市| 盖州市| 襄垣县| 科技| 西贡区| 二手房| 乌鲁木齐县| 内江市| 仙游县| 虹口区| 万荣县| 油尖旺区| 隆昌县| 巢湖市| 神池县| 郁南县|