C语言----指针详解

目录

一、指针的基本概念

1.1 什么是指针?

1.2 指针的创建

1.3 指针的大小

二、指针类型

2.1 指针类型的解引用

2.2 指针的加减运算

三、野指针

3.1 野指针的成因

3.2 如何规避野指针

四、常量指针与指针常量

4.1 常量指针

4.2 指针常量

五、指针的运算

5.1 指针+-整数

5.2 指针-指针

5.3 指针的关系运算

六、指针与数组

6.1 数组名与指针

6.2 指针与数组的操作

七、总结


在C语言中,指针是一个非常重要的概念,它不仅为程序员提供了直接访问和操作内存的能力,还是实现数据结构、函数参数传递、动态内存管理等高级功能的基础。

一、指针的基本概念

1.1 什么是指针?

在计算机科学中,指针是编程语言中的一个对象,它利用地址来直接指向存储在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,因此将地址形象化为“指针”。在C语言中,每个内存单元都有一个唯一的编号,这个编号被称为地址,也就是指针。指针变量是用来存放地址的变量。

1.2 指针的创建

在C语言中,可以通过取地址运算符 & 来获取变量的地址,并将该地址赋值给指针变量。例如:

int a = 10;
int *p = &a; // p是指针变量,存储了变量a的地址

1.3 指针的大小

指针的大小在32位平台是4个字节,在64位平台是8个字节。这个大小不会因为指针所指向的数据类型而改变

二、指针类型

2.1 指针类型的解引用

指针的类型决定了在解引用指针时能访问的字节数。例如,char*类型的指针解引用只能访问一个字节,而int*类型的指针解引用能访问四个字节。

#include <stdio.h>  
  
int main() {  
    int a = 10;  
    int *p = &a; // p 指向 a 的地址  
  
    printf("a 的值是: %d\n", a);  
    printf("p 指向的值是: %d\n", *p); // 通过指针 p 访问 a 的值  
  
    *p = 20; // 通过指针 p 修改 a 的值  解引用
    printf("修改后,a 的值是: %d\n", a);  
  
    return 0;  
}

三、野指针

3.1 野指针的成因

  1. 指针未初始化:如果指针变量在使用前没有被赋予有效的地址,它将指向一个随机的内存地址,这就是野指针。
  2. 指针越界访问:在数组操作中,如果指针指向了数组范围之外的地址,也会成为野指针。
  3. 指针指向的空间释放:如果指针指向的内存空间被释放(如通过free函数),而指针未被置为NULL,再次使用该指针时就会访问无效的内存。

3.2 如何规避野指针

  1. 指针初始化:使用指针前要确保它被正确初始化。
  2. 注意指针越界:在遍历数组等操作中,要确保指针在合法范围内。
  3. 及时置为NULL:如果指针指向的内存空间被释放,应立即将指针置为NULL
  4. 避免返回局部变量的地址:函数内部创建的局部变量在函数返回后会被销毁,返回其地址将导致野指针问题。
  5. 检查指针有效性:在使用指针前,检查其是否为NULL
#include <stdio.h>  
#include <stdlib.h>  
  
int main() {  
    int *p = malloc(sizeof(int)); // 动态分配内存  
    if (p != NULL) {  
        *p = 10;  
        printf("p 指向的值是: %d\n", *p);  
  
        free(p); // 释放内存  
        p = NULL; // 避免野指针  
    }  
  
    // 注意:这里不能访问 *p,因为它已经是 NULL 了  
  
    return 0;  
}

四、常量指针与指针常量

4.1 常量指针

常量指针指的是指针指向的值不能被修改,但指针本身可以指向其他地址。声明方式如const int *p 或 int const *p

4.2 指针常量

指针常量指的是指针本身的值(即地址)不能被修改,但指针指向的值可以被修改。声明方式如int *const p

#include <stdio.h>  
  
int main() {  
    int a = 10;  
    const int *cp = &a; // 常量指针,不能通过 cp 修改 a 的值  
    // *cp = 20; // 这将导致编译错误  
  
    int b = 20;  
    int *const pc = &b; // 指针常量,pc 本身的值(即地址)不能改变,但可以通过 pc 修改 b 的值  
    // pc = &a; // 这将导致编译错误  
    *pc = 30; // 合法操作  
  
    printf("a 的值是: %d\n", a);  
    printf("b 的值是: %d\n", b);  
  
    return 0;  
}

五、指针的运算

5.1指针的加减运算

指针类型还决定了指针进行加减运算时,地址变化的量。例如,int*类型的指针加1,地址增加4个字节(int占用4个字节);而char*类型的指针加1,地址只增加1个字节。

5.2 指针+-整数

可以通过给指针加上或减去一个整数来移动指针,使其指向新的地址。这种运算常用于遍历数组或字符串。

#include <stdio.h>  
  
int main() {  
    int arr[] = {10, 20, 30, 40, 50};  
    int *p = arr;  
  
    printf("p 指向的值是: %d\n", *p); // 10  
    printf("p+1 指向的值是: %d\n", *(p+1)); // 20  
  
    // 指针减法  
    int diff = (p + 4) - p; // 计算 p+4 和 p 之间的元素个数  
    printf("p 和 p+4 之间有 %d 个元素\n", diff); // 输出 4  
  
    return 0;  
}

5.3 指针-指针

两个指针相减,得到的是它们之间元素的个数(基于指针的类型)。这种运算常用于计算数组长度或两个元素之间的距离。

#include <stdio.h>  
  
int main() {  
    int arr[] = {1, 2, 3, 4, 5};  
    int *ptr1 = arr;        // ptr1 指向数组的第一个元素  
    int *ptr2 = arr + 3;    // ptr2 指向数组的第四个元素(即值为4的那个元素)  
  
    // 计算ptr2和ptr1之间相隔的元素数量  
    // 注意:这里的差值是基于ptr1和ptr2所指向的数据类型的大小来计算的  
    // 在这个例子中,因为ptr1和ptr2都是指向int类型的指针,所以差值为1意味着相差4个字节(假设int占用4个字节)  
    // 但当我们进行ptr2 - ptr1的运算时,得到的是它们之间相隔的元素数量,而不是字节数  
    int diff = ptr2 - ptr1;  
  
    printf("ptr2 和 ptr1 之间相隔了 %d 个元素\n", diff); // 输出:ptr2 和 ptr1 之间相隔了 3 个元素  
  
    return 0;  
}

5.4 指针的关系运算

指针之间可以进行关系运算(如<>==等),但需要注意,这种运算通常只在指向同一数组的元素时才有意义。

六、指针与数组

6.1 数组名与指针

数组名在大多数情况下代表数组首元素的地址,因此可以作为指针使用。但数组名不是指针变量,其类型是指向数组元素类型的指针。

6.2 指针与数组的操作

通过指针可以方便地遍历和修改数组中的元素。例如,使用指针进行数组的初始化、赋值、打印等操作。

#include <stdio.h>  
  
int main() {  
    int arr[] = {1, 2, 3, 4, 5};  
    int *p = arr; // p 指向数组的首元素  
  
    for (int i = 0; i < 5; i++) {  
        printf("%d ", *(p + i)); // 使用指针 p 遍历数组  
    }  
  
    printf("\n");  
  
    // 或者使用指针算术  
    for (p = arr; p < arr + 5; p++) {  
        printf("%d ", *p);  
    }  
  
    return 0;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值