C语言 结构体指针强制转换,c中结构体指针的强制类型转换
1、結構體到結構體指針之間的轉換
a、結構體指針的強制類型轉換即結構體的數(shù)據(jù)成員在內存段當中的重新分配,結構體的存儲“內存對齊”請參看上篇博客,該論述實例如下:
#include
#include
struct A{
int num;
};
struct B{
int num;
char type;
int age;
};
int main()
{
struct A a;
a.num = 5;
char* tmp1 = (char *)(&(a.num));
tmp1 = tmp1 + 4;
*tmp1 = 'a';
int *tmp2 = (int *)(&(a.num));
tmp2 = tmp2 + 2;
*tmp2 = 32;
struct B *b = (struct B *)(&a);
std::cout << b->num << " " << b->age << " " << b->type << std::endl;
std::cout << sizeof(*b) << std::endl;
system("pause");
return 0;
}
輸出結果: ? 5 32 a ? ? ? 12
結果分析:按照結構體B在內存當中的存儲方式應該如下:1111???1xxx???1111,也就是sizeof(*b)的值為12(詳細計算看上篇)。
1、結構體定義了一個結構體A?a,它的存儲方式是1111,共占用4個字節(jié),存儲的值為5;
2、tmp1指針所指向的位置為第8個字節(jié)的位置,保存的值為a;tmp2指向的位置為第6個字節(jié)位置;
3、將A?a強制轉換成B?b,即需要按照結構體B對該a所對應的塊內存進行重新取值并賦值給B所對應的字段,得到的會是如下結果:1~4字節(jié)存儲的是5,5~8字節(jié)存儲的是10,9~12字節(jié)存儲的是a
理解如下圖:
b、類型轉換也可以根據(jù)如下理解:
例如:b->num?:?將?struct?A?a?所指向的內存單元以?struct?B?b的分布方式(利用?b)取得偏移為num?的值。
結構體聲明如何內存的分布,結構體指針聲明結構體的首地址,結構體成員聲明該成員在結構體中的偏移地址。
解釋如下:
1、首先要明確struct?B?b本身有一個值(在32位機上一般是32位),這個值代表著某個內存地址,比如這個首地址值是0x30000000,由于b被定義Struct?B類型,那么編譯器在編譯源文件時就會認為b指向的是一個struct?B的結構,這個結構的內容由一段連續(xù)的內存存儲,(b->num)(b->type)(b->age)在struct?B的定義中肯定是存在num、type、age三個的,這幾個變量對一個struct?B結構的地址偏移量是固定的,也就是說只要知道一個struct?B結構的起始地址,就能計算出這個結構所包含的num、type、age的地址,由于B?b的地址已知(由A?a強制轉換而來,所以編譯器知道這個地址即a的首地址),b所含的num離b的偏移量已知,那么就能通過b實現(xiàn)對num的取值,在編譯器編譯C文件的時候并不管b中的nun是否定義
2、b被定義為struct?B,而B中又包含b,那么編譯器就認為b所指向的結構中存在num
3、b->num如果不發(fā)生保護錯誤,總是能取到一個值(這個值就是對b偏移一定距離的內存單元中的值),只是這個值不能確定是否是你期望的值
4、再次提醒,變量的值是存儲在內存中的,每個內存字節(jié)對應一個內存地址,而內存存儲的值本身是沒有整型,指針,字符等的區(qū)別的,區(qū)別的存在是因為我們對它們有不同的解讀,b的值就是一個32位值,并且存儲在某個內存單元中,通過這個32位值就能找到b所指向的結構的起始地址,通過這個起始地址和各個結構所包含變量離起始地址的偏移對這些變量進行引用,b->num只是這種引用更易讀的寫法,只要b是指向num?的指針,那么b的值就肯定存在,b存在,偏移量已知,那么b->num就肯定存在,只是要記住,b->num只是代表了對num一定偏移地址的值
5、假如b->num所對應的這段內存從未有進行過操作,那么其值就是系統(tǒng)上電啟動之后的內存的默認值,如果有其他程序使用過,那么其值就是其他程序執(zhí)行后在這段內存中留下的值,總之,每個正常工作的內存單元中都是有值的,無論這些值是否是我們所需要的,它們始終是存在的。你可以把內存想象成一個大數(shù)組,當你在程序中定義了一個數(shù)組,但是并沒有初始化,但是你也可以引用數(shù)組元素,只是引用的值是未知的,道理是類似的
2、將int強制類型轉換為結構體類型
typedef?struct?eg
{
int?x;
int?y;
}eg;
int?point?=?0x30000000;
eg?*peg?=?(eg*)point;
可以看到point本身只是個整型變量,但是這樣的賦值是合法的,peg->x的值是0x30000000開始的四字節(jié),peg->y是0x30000004開始的四字節(jié)。
解釋如下:
不是說某個地址有那個結構體你才能引用,即使沒有,你也能引用,因為你已經告訴了編譯器param變量就是指向一個PAINT_PARAM結構體的變量并且指明了param的值,機器碼的眼中是沒有數(shù)據(jù)結構一說的,它只是機械的按照指令的要求從內存地址取值,那剛才的例子來說,peg->x,peg->y的引用無論0x30000000是否存在一個eg結構體都是合法的,如果0x30000000開始的8個字節(jié)存在eg結構體,那么引用的就是這個結構體的值,如果這個位置是未定義的值,那么引用的結果就是這8個字節(jié)中的未定義值,內存位置總是存在的,而對內存中值的引用就是從這些內存位置對應的內存單元取值。
總結
以上是生活随笔為你收集整理的C语言 结构体指针强制转换,c中结构体指针的强制类型转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外夹式超声波艾默生流量计安装步骤
- 下一篇: 转行做产品经理,应该如何入手