目录
前言
该部分会介绍指针的基本知识,比如什么是指针、指针的类型、野指针等基本概念,以及指针和数组。其他关于指针的重要知识将会在指针进阶中提到。
一、什么是指针
指针不扎人,专门指内存!要理解指针一定要和内存结合起来。指针就是一个变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。对应到代码就是:
#include <stdio.h>
int main()
{
int a = 10;//在内存中开辟一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//将a的地址存放在p变量中,p就是一个之指针变量。
return 0;
}
二、指针的类型
指针的定义方式是: type + * 。char* 类型的指针是为了存放 char 类型变量的地址。 short* 类型的指针是为了存放 short 类型变量的地址,以此类推。总的来说,指针的类型决定了指针向前或者向后走一步有多大(距离)。
三、野指针
野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。野指针是很难避免的,构成野指针的原因主要有以下几点:
指针未初始化
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}
指针越界访问
#include <stdio.h>
int main()
{
int arr[10] = {0};
int *p = arr;
int i = 0;
for(i=0; i<=11; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
}
指针指向的空间释放
四、空指针
空指针是野指针的特殊情况。赋为 NULL 值的指针被称为空指针。NULL 指针是一个定义在标准库中的值为零的常量(即0x0)。一般程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的,它表明该指针不指向一个可访问的内存位置。
五、指针的运算
C 指针是一个用数值表示的地址。所以可以对指针执行算术运算。
1.指针+-整数
- 指针的每一次递增,它其实会指向下一个元素的存储单元。
- 指针的每一次递减,它都会指向前一个元素的存储单元。
- 指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型长度,比如 int 就是 4 个字节。
2.指针-指针
用于计算两个指针之间的元素的个数
int my_strlen(char *s)
{
char *p = s;
while(*p != '\0' )
p++;
return p-s;
}
3.指针的关系运算
指针可以用关系运算符进行比较,如 ==、< 和 >。如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证 它可行。
六、指针和数组
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
通过以上代码的结果,我们可以发现,数组名和数组首元素的地址是一样的。所以我们可以通过指针来访问数组。代码如下:
#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;
}
七、二级指针
众所周知,套娃很重要。指针同样可以套娃,所谓二级指针就是指向指针的指针。指针同样也是变量,指针也会有地址,那么同样可以用一个变量来存储该指针的地址,这个东西就是二级指针。同样还可以继续往上套娃。
八、指针数组和数组指针
听上去就很容易弄混,实际上比较好区分。指针数组是一个存放指针的数组,数组指针是指向数组地址的指针,其本质为指针。
1.指针数组
具体用法如以下的例子
#include <stdio.h>
const int MAX = 3;
int main ()
{
int var[] = {10, 100, 200};
int i=0;
int* ptr[MAX];
for ( i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; /* 赋值为整数的地址 */
}
for ( i = 0; i < MAX; i++)
{
printf("Value of var[%d] = %d\n", i, *ptr[i] );
}
return 0;
}
2.数组指针
定义方式如 int (*p)[n];首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。具体的情况会在指针进阶中提到。
总结
指针是C语言的灵魂,一定要记住,指针一定要结合内存来看。