簡體   English   中英

修改結構體的指針

[英]Modify pointer of pointer of struct

我創建一個結構,將指針的指針傳遞到函數中,然后調用malloc() 一切正常。 但是,如果我嘗試訪問內存,程序將凍結。 如果我調用另一個函數並更改對內存的訪問,則一切正常。

void test(TFeld *Feld, TEinstellung E)
{
int i;

    for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
    {
        Feld[i].Schiff_Vorhanden = false;
        Feld[i].Schiff_Versunken = false;
        Feld[i].Ueberprueft = false;
    }   
}

void initField (TEinstellung E, TFeld **Feld)
{
    int i;

    *Feld = (TFeld*)malloc(E.Groesse_X*E.Groesse_Y*sizeof(TFeld));

    test(*Feld,E);

    /*  for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
    {
        Feld[i]->Schiff_Versunken = (bool*)false;
    //  (*Feld[i]).Schiff_Versunken = false;
        //Feld[i]->Ueberprueft = false;
    } */
}

TFeld的定義:

typedef struct TFeld
{
    bool Schiff_Vorhanden = false;
    bool Ueberprueft = false;
    bool Schiff_Versunken = false;
} TFeld;

我注釋掉的部分只是在使用測試功能時崩潰了程序。

有人可以向我解釋這種行為。

有什么問題 ?

InitField() ,參數Feld被聲明為指向TFeld的指針。

*Feld因此是TFeld的指針。 它已正確初始化為正確大小的新分配內存區域。

然后,您調用test()並傳遞*Feld作為參數。 不幸的是,您也調用了Feld參數,因此這些變量的類型不同並且可能引起一些麻煩。 但這不是問題。 測試功能應該可以實現您的期望。

當您返回InitField() ,然后嘗試訪問已初始化的元素:

Feld[i]->Schiff_Versunken = ... //ouch !!!

這會將指針指向指針,並訪問該表中的第ith個指針。 但是由於指針的指針只是一個Poitner而不是數組,因此您將獲得一個完全損壞的指針。 然后,使用->假裝它指向TFeld來取消引用該惡意指針。 然后,當您向該惡意地址分配一個值時,您的行為就不確定(可能是段錯誤,可能凍結,可能是任何事情)。

編輯:有關指針解引用的其他信息:

運算符* ->[]具有必須習慣的優先順序 讓我們看一下TFeld **Feld

  • *Feld[i]*(Feld[i])相同,因為首先應用[] ,然后僅應用* 順便說一句,進一步講,應用指針算術規則,它與*(*(Feld+i)) 無論如何,這不是你想要的
  • *Feld[i].xxx*((Feld[i]).xxx)因為. 具有比*高的優先級。 因為Feld[i]不是TFeld類型, TFeld不會編譯
  • Feld[i]->xxx(Feld[i])->xxx (因為[]->具有相同的優先級,但是當兩者出現時,它們都是從左到右應用的)。 這進一步與(*(Feld[i])).xxx 仍然不是您想要的。

但是讓我們可視化以了解以不同順序應用取消引用的影響。 最重要的是您需要的。 根本是應避免的事情:

在此處輸入圖片說明

怎么解決 ?

我建議將注釋掉的部分更改為:

for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
{
    (*Feld)[i].Schiff_Versunken = false;
    (*Feld)[i].Schiff_Versunken = false;
    (*Feld)[i].Ueberprueft = false;
} 

或者,如果您不喜歡星星和黏附:

    Feld[0][i].Schiff_Versunken = false;
    Feld[0][i].Schiff_Versunken = false;
    Feld[0][i].Ueberprueft = false;

雙重定向總是有些棘手。 如有疑問,請添加一些括號。

最后一句話:我在這里假設InitField()是使用指向TFeld的有效指針來TFeld ,因此*Feld無疑會指向TFeld的指針。 如果是這種情況,則您的內存分配指針可能會寫入內存中的任何位置,從而再次導致內存損壞。 如有疑問,請對您的問題進行編輯,以顯示調用代碼,以便我檢查。

Feld是指向結構數組的指針。 因此,您必須(1)取消引用指針,然后(2)索引數組,最后(3)訪問struct內部的字段。

有兩種方法可以在for循環中編寫此代碼: 您更喜歡哪一個是口味問題:

(*Feld)[i].Schiff_Versunken = false;  // option 1
(*Feld + i)->Schiff_Versunken = false; // option 2

在函數內部直接進行操作時會有所不同。 因為這里Feld是指向test()結構的指針,而它是指向initField()結構的指針。

當您使用malloc()時,指向該結構的指針已初始化,因此在test()內部訪問時不會崩潰。 但是指向該指針的指針仍未初始化,因此在initField()引起了seg錯誤。

因此,您必須正確分配雙指針。 檢查此鏈接以供參考: C-使用雙指針的動態內存分配

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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