1. 程式人生 > >C 語言 二級指標的使用

C 語言 二級指標的使用

#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 專業操作, 最終你會發現程式進入了一個報錯的,  此時的最後一個解引用