簡體   English   中英

在C中對結構進行類型轉換

[英]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是一個指針,並且您的代碼使用與號將其作為指針,因此該值不會寫入t2status字段; 它直接寫入指針本身的空間。 這將解決問題,將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM