C 語言 二級指標的使用
阿新 • • 發佈:2019-05-19
#include <stdio.h> #include <stdlib.h> typedef struct node Node; struct node { int data; struct node* next; struct node* prev; }; Node head; Node* insert(Node* ph, Node* newData) { Node** link = &ph; while (*link && (*link)->data < newData->data) { link = &(*link)->next; } newData->next = *link; *link = newData; return ph; } Node* delNode(Node* pH, int data) { Node** link = &pH; Node* old_node; while (*link && (*link)->data != data) { link = &(*link)->next; } if (*link) { // free node; *link = (*link)->next; } return pH; } void remove_list_entry(Node* entry) { // The "indirect" pointer points to the // *address* of the thing we'll update Node** indirect = &head; // Walk the list, looking for the thing that // points to the entry we want to remove while ((*indirect) != entry) indirect = &(*indirect)->next; // .. and just remove it // 修改指標地址中的內容. *indirect = entry->next; } Node* init(int data) { Node* node = malloc(sizeof(Node)); memset(node, 0, sizeof(Node)); node->data = data; return node; } int main() { memset(&head, 0, sizeof(Node)); Node* new = init(0); insert(&head, new); Node* new1 = init(1); insert(&head, new1); Node* new2 = init(2); insert(&head, new2); Node* new3 = init(3); insert(&head, new3); delNode(&head, 2); Node* idx = &head; while (idx != NULL) { printf("%d\r\n", idx->data); idx = idx->next; } return 0; }
如上的程式碼主要是在參考linus 大神的good taste的風格,編寫的測試程式碼, 不可以商用[程式碼是有缺陷的, 在釋放記憶體的問題上];
問題的總結:
假設
int a=10; (1)
int* p= &a; (2)
int ** pp= &p; (3)
二級指標, 學過C 語言的大家都知道, 這個是獲取某個指標地址後的結果.
會提出2個問題:
1 如果解引用後, 重新進行賦值處理, 會引起那些資料的變化
主要考慮*p, &p,*pp, 這些值的變化
2 如果此時做 &(*pp) 這樣的操作, 會不會有新的情況出現, 主要是內容的變化.
如果在使用的過程中, 如果對該二級指標進行了解引用, 那麼解引用後,
該(*pp)的內容是什麼呢, 實際就是p 的值. 那麼此時, 如果對 *pp 進行修改, 則會出現一個新的情況就是, 會修改步驟(2)中的關係,
#include <stdio.h> #include <stdlib.h> int main() { int a = 1; int b = 2; int *pa = &a; int *pb = &b; int** ppa = &pa; int** ppb = &pb; fprintf(stdout, "[before] a addr is:%d\r\n", &a); fprintf(stdout, "[before] b addr is:%d\r\n", &b); fprintf(stdout, "[before] pa value is:%d\r\n", pa); fprintf(stdout, "[before] pb value is:%d\r\n", pb); fprintf(stdout, "[before] pa addr is:%d\r\n", &pa); fprintf(stdout, "[before] pb addr is:%d\r\n", &pb); fprintf(stdout, "[before] ppa value is:%d\r\n", ppa); fprintf(stdout, "[before] ppb value is:%d\r\n", ppb); fprintf(stdout, "[before] *ppa value is:%d\r\n", *ppa); fprintf(stdout, "[before] *ppb value is:%d\r\n", *ppb); //驗證2 問題, // 對 &(*ppa) 的結果一窺究竟 fprintf(stdout, "[after] &(*ppa) value is:%d\r\n", &(*ppa)); fprintf(stdout, "[after] &(*ppb) value is:%d\r\n", &(*ppb)); // 1 繫結關係的修改, // 具體會修改到那個層次? ppb = &pb; // 需要特別注意,此處會有2個寫法 // 如果是 *ppb = &pb; // 重點關注型別和資料的變化. 影響的了pb的值, 3406744->3406720, // *ppb = &pb; /* [before] a addr is:3406756 [before] b addr is:3406744 [before] pa value is:3406756 [before] pb value is:3406744 [before] pa addr is:3406732 [before] pb addr is:3406720 [before] ppa value is:3406732 [before] ppb value is:3406720 [before] *ppa value is:3406756 [before] *ppb value is:3406744 [after] &(*ppa) value is:3406732 [after] &(*ppb) value is:3406720 [after] ppb value is:3406720 [after] *ppb value is:3406720 [after] pb value is:3406720 [after] b addr is:3406744 [after] b value is:2 [after] **ppb value is:3406720 */ // 如果是 ppb = &pb; // 這個是修改, ppb 的值. fprintf(stdout, "[after] ppb value is:%d\r\n", ppb); fprintf(stdout, "[after] *ppb value is:%d\r\n", *ppb); fprintf(stdout, "[after] pb value is:%d\r\n",pb); fprintf(stdout, "[after] b addr is:%d\r\n", &b); fprintf(stdout, "[after] b value is:%d\r\n", b); fprintf(stdout, "[after] **ppb value is:%d\r\n", **ppb); //fprintf(stdout, "[after] ***ppb value is:%d\r\n", ***ppb); // 通過如上的測試, 這樣的修改, 僅僅是修改了, 二級 /* [before] a addr is:3145260 [before] b addr is:3145248 [before] pa value is:3145260 [before] pb value is:3145248 [before] pa addr is:3145236 [before] pb addr is:3145224 [before] ppa value is:3145236 [before] ppb value is:3145224 [before] *ppa value is:3145260 [before] *ppb value is:3145248 [after] &(*ppa) value is:3145236 [after] &(*ppb) value is:3145224 [after] ppb value is:3145224 [after] *ppb value is:3145248 [after] pb value is:3145248 [after] b addr is:3145248 [after] b value is:2 [after] **ppb value is:2 */ return 0; }
如上測試的程式碼, 注意在使用的過程中, 會有如下的問題,
1 如果是調整二級指標的指向, 需要使用 ppb=&pb;
2 如果使用了二級指標, 且調整的時候,並且使用了 *ppb = &pb, 這樣的操作, 就需要特別注意了, 可以 使用**ppb, 但是是沒有任何意義,
千萬不要使用 ***ppb 專業操作, 最終你會發現程式進入了一個報錯的, 此時的最後一個解引用