[英]Type casting of structures in C
最近,我在C中看到了一個我很納悶的代碼。
代碼的簡單形式如下
typedef unsigned int uint32_t;
typedef struct
{
uint32_t easy;
uint32_t hard;
}mode;
typedef struct
{
uint32_t status;
}type;
int main()
{
type t2 = { 0 };
type* t1 = NULL;
t1 = &t2;
t1->status = 99;
((mode*)&(t1))->easy = 1;
printf("%d", ((mode*)&(t1))->easy);
scanf_s("%d", &((mode*)&(t1))->hard);
printf("%d", ((mode*)&(t1))->hard);
printf("%d", t1->status);
}
但是,當我執行上述操作時,我在最后一個printf語句中得到一個錯誤,即“ 訪問沖突讀取位置0x00000001 ”。
任何幫助將不勝感激。
該行在分配給指針的空間中存儲一個int
:
((mode*)&(t1))->easy = 1;
由於t1
是一個指針,並且您的代碼使用與號將其作為指針,因此該值不會寫入t2
的status
字段; 它直接寫入指針本身的空間。 這將解決問題,將1
寫入status
字段,這也是easy
的別名:
((mode*)t1)->easy = 1;
解決了這個問題之后,下一個問題就發生在scanf_s
行上。 即使刪除了“&”號,此行也具有未定義的行為:
scanf_s("%d", &((mode*)&(t1))->hard); // <<== Undefined behavior
scanf_s("%d", &((mode*)(t1))->hard); // <<== Also undefined behavior
原始行嘗試通過分配給t1
指針的位置寫入堆棧內存,從而從scanf_s
返回時導致堆棧損壞。
固定行嘗試寫入超出type
struct末尾的hard
位置。
請注意,這是確定投type*
以mode*
和訪問easy
就可以了:當兩個struct
■找相同的初始成員,你可以自由地投三分球,以一個struct
到指針類型的其他的struct
。
起初,一切看起來都很好。 甚至我也被困在為什么會引發訪問沖突。 順便說一句,違反是在最后一個printf上。
然后我意識到了錯誤。 t1已經是一個指針。 他們不必到處都做&(t1)。 這改變了t1本身的內容,而不是它指向的結構。 其次,沒有足夠的內存分配給* t1用作模式,因此您可以將t2設置為mode類型並在將其地址分配給t1之前對其進行強制轉換。 否則,由於t1剛好位於t2之后的堆棧上,因此您在硬更改時最終將值編輯為t1
所以簡單的解決辦法是
typedef unsigned int uint32_t;
typedef struct
{
uint32_t easy;
uint32_t hard;
}mode;
typedef struct
{
uint32_t status;
}type;
int main()
{
mode t2 = { 0 };
type* t1 = NULL;
t1 = (type*) &t2;
t1->status = 99;
((mode*)(t1))->easy = 1;
printf("%d", ((mode*)(t1))->easy);
scanf_s("%d", &((mode*)(t1))->hard);
printf("%d", ((mode*)(t1))->hard);
printf("%d", t1->status);
}
一切都按預期進行。 沒有訪問沖突。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.