学习视频链接
https://www.bilibili.com/video/av52627832
内存四区
地址:
把内存以单个字节为单位分开。对每一个字节进行编号。这就是地址
int a;
&a //取出a的地址
首地址:一段内存空间中第一个存储单元的地址。
指针变量:
地址是一些编号。一种数据
指针变量的定义:
数据类型 *变量名
int *p1;
char *p2;
数据类型指明指针指向的数据类型。因为数据类型不同。所占字节数不同。所以需要指明数据类型以便正确获取数据。数据类型是什么,该指针变量就只能保存什么类型的数据的地址。
*表明这是一个指针变量
指针变量的赋值
int a = 1;
int *p;
p = &a;
&号
取地址符。取出指定变量的地址
指针变量的引用
接上一个代码
访问a的方式
printf(“%d”,a);
printf(“%d”,*p);
这里的*号为取值符。可通过地址取出对应的数据,即返回某一个地址中的值。
两种*号:
野指针:不能明确指向的指针变量
int *a;
指针定义时,没有被初始化。或者指针指向的内存空间被释放了。它就会指向随机区域。任何指针变量在定义的时(除了static修饰的指针变量)是不会被置空的。而是默认为一个随机的地址值。
由于地址值不可控。所以将会有很大的安全隐患。
解决办法就是定义好指针后手动赋值为NULL
int *a = NULL;
空指针:
void *
一开始不确定存放的变量是什么类型的。就可以使用void *。之后要用的时候再转换成其他的数据类型。再动态内存分配中使用。
指针变量的运算:(指针偏移)为了访问地址旁边的一些内存
+ - ++ --
指针变量的加减。以指针所指向的类型空间单位进行偏移
char *p1; //char类型。占1个字节 所以p1+1偏移量是1字节
int *p2; //int类型。占4个字节,所以p2+1偏移量是4字节
double *p3; //double类型。占8个字节。所以p3+1偏移量是8字节
一维数组与指针
int a[5];
这里a是其实一个指针。指向的是a[0]的地址
但是 a 不是 &a[0]。虽然他们地址相同。但是性质不相同
a指向的是a[0]。是a[0]这个int类型数据的指针。a 类型是int *
&a指向的是整一个a这个数组。并不是a[0]。只是a[0]恰好和a这个数组首地址一样而已。&a类型是int (*)[5]。是一个数组指针。
演示下实例:
由于打印出来是16进制。14其实就是10进制的20。也就是说&a把数组当作一个整体。a有5个int类型的元素。一个int类型占4个字节。所以&a+1新开了20个字节的空间。而a是指向a[0]的是一个int *类型的指针。int类型只占4个字节。所以a+1只新开了4个字节的空间。
这里需要搞清楚首地址和指针偏移的概念。首地址是一段空间中的第一个存储单元的地址。这个“一段空间取决于指针指向的数据类型”。以上例为例。a指向的是a[0]。a[0]的首地址就是int 4个字节中的第一个字节。而&a指向的是整一个数组。这一个数组的首地址是数组里5个元素中第一个元素的地址。
访问数组的元素:
int *p = a;
printf(“%d”,p[1]);
printf(“%d”,*(p+1)); //从a[0]开始偏移一位。4个字节。刚好就是a[1]
细节:
1、*(p+1) 需要括号,*p++不需要括号
因为*比+优先级高。而*和++优先级一样。就从右往左执行。
如果*(p+1)不加括号。就是变成了取出a的值后再加1了 => (*p) + (1)
2 、*(p+1)p 不会改变。*p++ p会变
因为++会影响到自身变量。所以p++后就不是a[0]了。指针指向地址变成a[1]。
3、a不能++。而p可以++
因为a是一个数组名。虽然也是一个指针。但是如果数组名都++了。那这个数组就没有意义了。为了防止这个情况。数组名是不能++的。想++只能新建一个指针将a的首地址丢过去。新指针就可以用++。
二维数组与指针
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
虽然看起来是三行4列的。但是在内存中还是一个连续的存储空间。可以看作是一个一维数组的组合。
数组名:a
a是二维数组的首地址。
a指向二维数组的第一个存储单元
所以a指向a[0] 这个一维数组。类型为int (*) [4] 由于a[0]这个一维数组中有4个int。所以a + 1新增字节为16个字节
a[0]是一维数组的数组名。a[0]指向a[0][0] 类型为int * 由于a[0]指向一个int数据。所以a + 1新增字节为4 个字节
所以:
a指向一维数组
a[0]指向一个int数据
可以看到a+1新开了16个字节。而a[0]+1只开了4个字节
多维数组也如此
二维数组取值用指针法如下:
取m行n列的元素
a[m][n] => *(a[m] + n) => *(*(a+m) + n)