簡體   English   中英

取消引用指針會殺死它的值?

[英]Dereferencing pointer kills its value?

我有一個方法應該在數組的末尾添加一個“節點”。 當我找到一個存儲值的地方(有效)時,這會奇怪地從舊地址中刪除該值。

void appendAtEndOfArray(struct node * item,struct node * arrayPointer){
    int i=0;
    while (arrayPointer[i].name!='\0') {
        i++;
    }
    arrayPointer[i]=*item; // after this the original memory at &item is changed to '\0'
}

這可能很容易,但我是C和整個指針的新手....

我這樣稱呼方法:

void addVertice(char source, char destination,int cost){
    struct node * sourceNode = addNode(source);
    struct node * destinationNode = addNode(destination);
    appendAtEndOfArray(destinationNode,sourceNode->children);
    appendAtEndOfArray(sourceNode,destinationNode->parents);
}

我的節點定義如下:

struct node            {
    char name;
    bool visited;
    int distance;
    struct node *children[30];
    struct node *parents[30];
} nodes[30];

struct node * addNode(char name){
    int n=getNodeByName(name); // if exists reuse
    if (n==-1) {
        n=++lastNodeIndex;
    }
    nodes[n].name = name;
    nodes[n].visited=false;
    return &nodes[n];
}

有人可以指出我做錯了什么嗎?

您看到此行為是因為您在appendAtEndOfArray的定義與傳遞給它的參數之間存在類型不匹配。 NuclearGhost在評論中指出了這一點。 正如他所說,函數聲明需要更改為

void appendAtEndOfArray(struct node * item, struct node * arrayPointer[])

更改數組參數后看到的“錯誤訪問”錯誤來自while循環。 在更正函數聲明之后, arrayPointer[i]具有類型struct node * 因為您現在通過指針訪問struct成員,所以. (點)運算符必須更改為->

while (arrayPointer[i]->name != '\0') {

現在你可以采取twalberg的建議直接分配item的價值:

arrayPointer[i] = item;

還有一個問題需要糾正: arrayPointer[i]是指針類型,因此它可以具有空值。 在取消引用指針之前需要檢查該條件,否則程序可能會因分段錯誤而崩潰:

while (arrayPointer[i] && (arrayPointer[i]->name != '\0')) {

編輯:關於代碼“奇怪地刪除舊地址中的值”的擔憂背后的“原因”的補充說明。

在原始代碼中,當您將sourceNode->children傳遞給appendAtEndOfArray ,編譯器會因類型不匹配而發出警告,但無論如何都會生成代碼。 它可以這樣做,因為你傳入的值和函數所期望的值都是內存地址 - 指針的“類型”只是確定編譯器如何處理指針所指的內存,所以不必實際的數據轉換執行。

在我的機器上,一個32位的x86平台,指針是4字節,你的struct node類型是252字節(由於填充char和bool類型最多4個字節,每個)。 appendAtEndOfArray分配item到的第一個元素arrayPointer ,如(從原來的代碼):

arrayPointer[i]=*item;

系統將252字節的數據從結構復制到用於保存4字節指針的內存位置。 結果, arrayPointer[i]之后的下一個248個字節被覆蓋。 由於節點是在數組中分配的,這意味着nodes數組中下一個節點的一部分將被覆蓋。

例如,考慮呼叫

appendAtEndOfArray(destinationNode,sourceNode->children);

假設sourceNode->children數組為空,因此將destinationNode分配給第0個元素。 由於賦值實際上是將整個struct內容寫入第0個元素的內存位置,這將覆蓋sourceNode->children (120字節)的所有30個元素以及所有sourceNode->parents (另外120個字節),另外12個字節的數據溢出到節點數組中的下一個元素,(在我的機器上)覆蓋了namevisited成員。

暫無
暫無

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

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