一级指针和二级指针,取地址和不取地址调用函数区别及其应用

2024-06-15 08:47:43 浏览数 (1)

1.指针定义区别

一级指针是指向某个数据的指针,它存储的是该数据的内存地址。通过一级指针可以访问和修改该数据的值。一级指针多用于单个数据的操作,例如传递参数、返回结果等。

二级指针是指向一级指针的指针,它存储的是一级指针的内存地址。通过二级指针可以访问和修改一级指针指向的数据的值。二级指针多用于对一级指针进行操作,例如动态内存分配和释放、指针数组等。

一级指针和二级指针的应用主要有以下几个方面:

  1. 动态内存管理:通过二级指针可以对动态分配的内存进行管理,例如创建和销毁动态数组、链表等数据结构。
  2. 参数传递:通过一级指针可以将变量的地址传递给函数,并在函数中修改变量的值。通过二级指针可以将指针的地址传递给函数,并在函数中修改指针指向的数据。
  3. 返回多个值:通过二级指针可以在函数中修改指针指向的数据,并将修改后的数据通过指针返回。
  4. 多级数据结构:通过二级指针可以实现多级数据结构,例如二维数组的动态分配和访问、树的遍历和修改等。

总之,一级指针和二级指针在C和C 中是非常重要的概念,能够帮助程序员更灵活地操作内存和数据结构。对于初学者来说,理解和掌握一级指针和二级指针的使用方法是非常基础和重要的一步。

2.举例比较

代码语言:javascript复制
struct Node{
    int data;
    Node* next;
};

void insertNode(Node** head, int data){
    Node* newNode = new Node();
    newNode->data = data;
    newNode->next = *head;
    *head = newNode;
}

int main(){
    Node* list = nullptr;
    insertNode(&list, 1);
    insertNode(&list, 2);
    insertNode(&list, 3);
    
    Node* currentNode = list;
    while(currentNode != nullptr){
        cout << currentNode->data << " ";
        currentNode = currentNode->next;
    }
    
    return 0;
}

在上述示例中,insertNode函数接收一个二级指针head作为参数,它通过将新节点的next指针指向*head,然后将*head指向新节点,来在链表的前端插入一个节点。

main函数中,通过传递&list作为参数调用insertNode函数,实际上是将链表的头指针list的地址传递给了二级指针head。这样,在insertNode函数中可以通过修改*head来改变链表的头指针。最终,遍历链表并输出结果。

3.函数参数调用时取地址和不取地址的区别

代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>

struct Node{
    int data;
    struct Node* next;
};

void insertNode(struct Node* head, int data){
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    
    // 将新节点插入链表末尾
    if(head == NULL){
        head = newNode;
    } else {
        struct Node* temp = head;
        while(temp->next != NULL){
            temp = temp->next;
        }
        temp->next = newNode;
    }
}

void printList(struct Node* head){
    struct Node* currentNode = head;
    while(currentNode != NULL){
        printf("%d ", currentNode->data);
        currentNode = currentNode->next;
    }
    printf("n");
}

int main(){
    struct Node* list = NULL;
    
    insertNode(list, 1);
    insertNode(list, 2);
    insertNode(list, 3);
    
    printList(list);
    
    return 0;
}

在上述示例中,insertNode函数接收一个指向链表头节点的指针head作为参数,用于将新节点插入链表末尾。然而,这里的参数head并未取地址传递,即没有改变main函数中的链表list

运行以上代码,输出为空,因为链表并没有被正确构建。原因在于在insertNode函数中,head是一个局部变量,它只是指向了传递进来的链表头节点的一个副本,所以对head的修改不会影响实际的链表。

为了解决这个问题,我们需要将头节点的指针的地址传递给insertNode函数。修改main函数中的调用如下:

代码语言:javascript复制
insertNode(&list, 1);
insertNode(&list, 2);
insertNode(&list, 3);

将链表头节点指针的地址传递给insertNode函数后,可以正确构建链表,并输出结果:

代码语言:javascript复制
1 2 3

通过取地址传递参数,可以在函数内部修改实际的链表,使对链表的操作在函数外部可见。

0 人点赞