文章目录
-
指针是什么 - 指针和指针类型
- 野指针
- 指针运算
-
二级指针
-
指针数组
指针是什么?
指针的理解有两个要点:
1.指针是内存一个很小单元的编号,也就是地址。
2.平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
总结:指针就是地址,口语中说的指针通常指的是指针变量。
#include <stdio.h>
int main()
{
int a=10;//在内存上开辟一块空间
int* p=&a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//a变量占用4个字节的空间,这里将a的4个字节的第一个字节的地址存放在p变量中
//p就是一个指针变量。
return 0;
}
总结:
指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。
那么问题来了:
(1)一个小的单元到底是多大?
(2)如何编址?
经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。
对于32位的机器,如果有32根地址线,那么假设每根地址线在寻找址的时候产生的高电压和低电压就是1和0
那么32根地址线产生的地址就会是:
这里就有2^32个地址
每个地址表示一个字节,那么就可以给4G的空间进行编址。
同理64位的机器也是如此。
所以在32位的机器上,地址要用4个字节的空间来存储,一个指针变量也就是4个字节。
64位的机器上,地址要用8个字节的空间来存储,一个指针变量也就是8个字节。
小结:
1、指针是用来存放地址的,地址是唯一标识一块内存空间的。
2、指针在32位平台上的大小是4个字节,在64位平台上是8个字节。
指针和指针类型
指针的类型有:
从这里我们不难看出,指针的定义方式是:类型+*
其实
char*类型的指针是为了存放char类型变量的地址
int*类型的指针是为了存放int类型变量的地址
那指针类型的意义是什么?
操作了4个字节
char*类型的操作了1个字节
所以指针类型决定了,指针在被解引用的时候,访问的权限。
整型指针解引用访问4个字节。
字符指针解引用访问1个字节。
注意:这里并不是发生了截断。
这里的int*类型走了4个字节,而char*类型走了1个字节。
所以指针类型决定了指针向前后向后走一步,走多大距离。
野指针
野指针成因:
1、未初始化
2、指针越界访问
3、指针指向的空间释放
那么如何有效的规避野指针呢
1、指针初始化
2、小心指针越界
3、指针指向空间释放即放置NULL
4、避免返回局部变量的地址
5、指针使用之前检查有效性
就像这样
指针运算
没想到指针还可以加减运算吧!
指针+-整数
指针-指针
指针-指针的绝对值其实是得到的是指针和指针之间元素的个数,但前提是两个指针必须指向同一个空间。
举个例子写个函数模拟实现strlen的功能
#include <stdio.h>
int my_strlen(char* str)
{
char* start = str;//先把首元素地址存起来
while (*str)
{
str++;//找到\0之后退出循环
}
return str - start;
}
int main()
{
char arr[] = "absdfgf";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
指针的关系运算
代码简化,代码修改如下:
实际上在绝大多数编译器上是可以编译的,但是我们应该还是要避免这样写,因为标准并不保证它可行 。
标准规定:
指针和数组
由此可见数组名和数组首元素的地址是一样的
可以得出结论:数组名是首元素的地址。(有2中情况除外)
1、sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小。
2、&数组名,数组名表示整个数组,取出的是整个数组的地址。
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
int* p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ",*(p+i));
}
return 0;
}
这里我们就可以通过首元素的地址来访问数组中的每个元素了。但是数组和指针不是一回事,数组是一块连续的空间,指针是存放地址的变量。这并不妨碍我们可以通过指针来访问数组。
二级指针
*pa 通过对pa中的地址进行解引用,这样找到的是 p , *pa 其实访问的就是 p
**pa 先通过 *pa 找到 p,然后对 p 进行解引用操作: *p ,那找到的是 a
这里二级指针可以理解的话,那么以此类推自己可以写出三级指针……
指针数组

二级指针的运用,代码如下:
#include <stdio.h>
int main()
{
int a[] = { 1,2,3,4,5 };
int b[] = { 2,3,4,5,6 };
int c[] = { 3,4,5,6,7 };
int* arr[3] = { a,b,c };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
是不是感觉像一个二维数组,这里的arr就是指针数组。
本章完!
喜欢作者就点个赞吧!!!