07_指针

地址与指针

地址:数据在内存中的存储位置编号,是常量
指针:本质是地址
指针变量:存储的数据是地址,占4字节内存
类型* 标识符;
如 int * p=&a; //表示该指针变量p的值等于a的地址
取地址符 &
* 解引用,取内容

指针变量取了谁的地址,就指向谁

int a=10, b=20, c=30;
int *p1, *p2, *p3;
p1=&a;
p2=&b;
p3=&c;
printf(“%d\n”, *p1); // *p1表示取内容,这里输出a的值10

//定义指针的时候,要马上给指针变量赋值,防止出现野指针(没有任何指向)
int *k1=NULL;//赋值为空
float *k2=NULL;
doubel *k3=NULL;
printf(“%d\n%d\n%d\n”, sizeof(k1), sizeof(a2), sizeof(a3));
//指针变量占内存都为4个字节,上述显示三个4

可以通过指针变量修改数据的值

int arr[10]={1,2,3,4,5,6,7,8,9,10};
for (int i=0;i<10;i++)
{
\quad print(“%p\n”, &arr[i]); //%p表示输出地址
}

int *p=&arr[0]; //数组首地址
int *p=arr; //数组名本身表示这个数组的首地址
p+=9;//表示指针的偏移,偏移一次所移动的字节数跟类型相关
printf(“%d\n”, *p); //输出的是偏移9位的值,即arr[9]的值 10

常量字符串

char *p1=“hello world”;
printf(“%d\n”, sizeof(p1)); //会输出4
printf(“%d\n”, strlen(p1)); //会输出11

指针函数与函数指针

指针函数:是一个函数,但是这个函数的返回值类型是一个指针

int * fun()
{
\quad int a=10;//a 是一个局部变量
\quad return &a;
}

函数指针:是一个指针,指向的是一个函数
函数指针的定义格式:函数的返回值类型(*函数指针名)(函数的形参列表);

void fun1(int a, int b)
{
\quad printf(“%d\n”, a+b);
}
void (*pFun)(int a, int b);
int main()
{
\quad pFun=fun1; //函数名就是代表其首地址
\quad pFun(1,2);
}

typedef int(*pF)(int,int);//函数指针取别名,别名就是他自己
//并且别名可以当作类型去使用

常量指针与指针常量

常量指针:定义不用初始化,能改变指向,指向的内容不能被修改(保护实参不被函数形参调用修改)
const int *p;
指针常量: 定义的时候必须要初始化,不能改变指向,可以改变指向的内容
int * const p1;

大端存储和小端存储

数据的地址:0x12345678 存于 0x0~0x3这个4字节中
0x0 12
0x1 34
0x2 56
0x4 78
是大端存储;适合人的读取方式(进制的高位存在前)
0x0 78
0x1 56
0x2 34
0x4 12
是小端存储;x86CPU使用小端存储作为数据的存储方式

指针数组与数组指针

指针数组:是一个数组,存储的是指针
数组指针:是一个指针,指向的是一个数组(二维数组起)

int arr[3][3]=
{
1, 2, 3,
4, 5, 6,
7, 8, 9
};
int (*p)[3]=arr; //表示3列 ,定义了一个数组指针
//下面定义指针数组
int a=3, b=2, c=1;
int *p2=&a, *p3=&b, *p4=&c;
int *p1[3]={p2,p3,p4};

int n[3][4]
{
\quad {1, 2, 3, 4},
\quad {8, 7, 6, 5},
\quad {9, 10, 11, 12},
};
int(*pn)[4] = n; //数组指针
int *p[3]={n[1], n[0], n[2]}; //这是一个指针数组
int **pp=p; //二级指针
printf(“%d\n”, *(*(pp+1)+2)); //*(pp+1)=pp[1]即首地址往后移一位,这里变成了n[0],然后继续在n[0]首地址往后移2位,最后输出数字3
printf(“%d\n”, *(pp[2]-3)); // pp[2]是n[2]的首地址解引用得到数字9,然后左移3位,得到的输出为数字7

内存四区

栈区:存储局部变量,系统自动申请释放内存
静态全局区:存储的静态和全局变量数据,内存只会存在一份,只会初始化一次,在程序执行结束时被释放
堆区:手动申请的内存区域,需要我们手动释放存储的是函数
代码区:存储的是函数等等

结构体指针

结构体指针:指向一个结构体变量的指针。一个结构体变量的起始地址就是这个结构体变量的指针

typedef struct nodeDate
{
\quad int a;
\quad char name[20];
}node;
void main()
{
\quad node n;
\quad n.a=10;
\quad node *p=&n; //结构体指针,访问成员通过箭头->
p->a = 20;
}

动态内存分配

从堆区申请内存,自己使用
通过函数malloc, calloc, realloc申请(头文件 stdlib.h)
从堆区申请的内存是通过指针执行管理的
int *p=(int *)malloc(100); //申请100个字节
//赋值的条件是类型相同,因为malloc函数的返回类型不是int,这里用强制转换
*p =10;
*(p+1)=20; //申请的内存用来存数据
free( p);
释放内存用free函数
在释放内存的时候,所填的指针必须要指向内存的首地址

nt *p=(int *)malloc(sizeof(int)*25);

memset(p1,0,sizeof(int)*25); // 逐字节赋值(string.h)

int *p=(int *)realloc(p, sizeof(int)*50); //重分配内存,不会初始化
free§;
p=NULL;

int *p=(int *)calloc(25,sizeof(int)); //申请的内存系统会自动初始化为0

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值