#include
#include
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
#include
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 专业操作, 最终你会发现程序进入了一个报错的, 此时的最后一个解引用是错误的,