指针:存储地址的变量

本文介绍了C语言中的指针,包括指针的定义、内存地址概念、指针语法和内存访问,以及指针在数组、函数和堆空间中的应用。重点讨论了如何在堆上动态分配和释放内存,并强调了指针使用的规则和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

指针:一种特殊的变量

指针是C语言中的变量

  1. 可以用于保存具体值
  2. 特殊之处,指针保存的值是内存中的地址
内存地址是什么?
  • 内存是计算机中的存储部件,每个存储单元有固定唯一编号
  • 内存中存储单元的编码即内存地址
地址获取
  • C语言通过&操作符获取程序元素地址
  • &可以获取变量,数组,函数的起始地址
  • 内存地址的本质是一个无符号整数(4字节[32位],8字节[64位])
#include <stdio.h>
int main()
{
    int var =  0;
    printf("var = %d\n",var);
    printf("&var = %p\n",&var);
    return 0;
}
指针语法 type* pointer
指针内存访问: *pointer
  • 指针访问操作符(*)作用于指针变量即可访问内存数据
  • 指针类型决定了通过地址访问内存时的长度范围
  • 指针的类型统一占用4字节或8字节
初学指针的规则
  • Type* 类型的指针只保存Type类型变量的地址
  • 禁止不同类型的指针相互赋值
  • 禁止将普通数值当作地址赋值给指针

指针于数组

  • 使用取地址操作符&获取数组地址
  • 数组名可看作一个指针,代表数组中0元素的地址
  • 当指针指向数组元素时,可进行指针运算

对于指针与数组中

int a[] = {5,48,45,4};
int *p = a;
int i = 0;

有如下关系

a[i] == *(a+i) == *(p+i)
字符串

C语言中字符串常量的类型是什么?
答: char * 类型,一种指针类型。

指针移动组合
 int v = *p++
解读
  • 指针访问符(*)和自增运算操作符(++) 优先级相同
  • 先从p指向的内存中取值,然后p进行移动

指针与函数

深入函数
  • 函数的本质就是一段内存中的代码(占用一片连续的内存)
  • 函数拥有类型,函数的类型由返回类型和参数类型列表组成
//函数类型
//函数声明                  类型
int sun(int n)             int(int)
void swap(int *a,int *b)   void(int*,int*)
注意
  • 函数名就是函数体的起始地址(函数入口地址)
  • 通过函数名调用函数,本质位指定具体地址的跳转执行
  • 可以定义指针保留函数入口地址

函数指针(Type func(Type1 a,Type2 b))

  • 函数名即函数入口地址,类型Type(*)(Type1,Type2)
  • 对于func的函数,&func与func数值相同,意义相同
  • 指向函数指针:Type (*pEunc)(Type1,Type2) = func

函数指针参数

  • 函数指针的本质还是指针(变量,保存内存地址)
  • 可定义函数指针参数,使用相同代码实现不同功能
#include <stdio.h>
int add(int a,int b)
{
    return a+b;
}
int calculate(int a[],int len,int(*cal)(int,int))
{
    int number=a[0];
    int i=0;
    for(i=1;i<len;i++)
    {
        number=cal(number,a[i]);
    }
    return number;
}
int main(int argc, char const *argv[])
{
    int a[] = {1,2,3,4,5,6,7,8,9};
    printf("1+2+....+9=%d\n",calculate(a,9,add));
    return 0;
}

注意

  1. 函数指针只是单纯的保存函数入口地址
  2. 因此
    • 只能通过函数指针调用目标函数
    • 不能进行指针移动(指针运算)

指针与堆空间

内存区域不同,用途不同

  • 全局数据区:存放全局变量,静态变量
  • 栈空间:存放函数参数,局部变量
  • 堆空间:用于动态创建变量(数组)
堆空间的本质
  • 备用的“内存仓库”,以字节为单位预留的可用内存
  • 程序可在需要时从“仓库”中申请使用内存(动态借)
  • 当不需要在使用申请的内存时,需要及时归还(动态还)
如何在堆空间申请内存?如何归还?
预备知识 – void*
  • void类型是基础类型,对应的指针类型为 void*
  • void*是指针类型,其指针变量能够保存地址
  • 通过void*指针无法获取内存中的数据(无长度信息)

void*总结

  • 不可使用void*指针直接获取内存数据
  • void*指针可与其他数据指针相互赋值
堆空间的使用
  • 工具文件:stdlib.h
  • 申请:void* malloc(unsigned bytes)
  • 归还:void free(void* p)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
    int *p = malloc(2*sizeof(int));
    if (p != NULL)
    {
        *p = 1;
        *(p+1) = 2;
        for (size_t i = 0; i < 2; i++)
        {
            printf("%d ",p[i]);
        }
        free(p);
    }
    
    return 0;
}

堆空间使用原则

  • 有借有还
  • malloc申请内存后,应该判断是否申请成功
  • free只能释放申请到的内存,且不可以多次释放
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值