![](/img/trans.png)
[英]Dereferencing an incremented pointer causing the pointer to change its value?
[英]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個字節的數據溢出到節點數組中的下一個元素,(在我的機器上)覆蓋了name
和visited
成員。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.