什么是指针
百度中指针的概念
指针是内存中最小单元的编号,也就是地址。
什么是指针变量
平时口语中的指针,通常指的是指针变量,是用来存放内存地址的变量。
我们可以通过&(取地址操作符)取出变量的内存其实是地址,把地址可以存放到一个变量中,这个变量就是指针变量。
#include <stdio.h>
int main()
{
int a = 10;//在内存中开辟一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
// a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p就是一个指针变量。
return 0;
}
总结:
指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。
指针是用来存放地址的,地址是唯一标示一块地址空间的。
指针的大小在32位平台是4个字节,在64位平台是8个字节。
什么是指针类型
变量有不同的类型,有整形,浮点型,那指针有没有类型呢?
int num = 10;
p = #
要将&num保存到p中,我们知道p就是一个指针变量,那它的类型是怎样的呢?
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
char* 类型的指针是为了 char 类型变量的地址。
short* 类型的指针是为了存放short类型变量的地址。
int* 类型的指针是为了存放int类型变量的地址。
long* 类型的指针是为了存放long类型变量的地址。
…
指针类型决定了指针进行解引用操作的时候,能够访问空间的大小
#include <stdio.h>
int main()
{
int a = 0x11223344;//定义a为16进制的数
int* pa = &a;//定义指针变量pa
char *pc =(char*)&a;
printf("%p\n", &a);
printf("%p\n", pa);
printf("%p\n", pa+1);
printf("%p\n", pc);
printf("%p\n", pc+1);
return 0;
}
运行结果如下;
0x16d02ac88
0x16d02ac88
0x16d02ac8c//int类型的指针能够访问4个字节
0x16d02ac88
0x16d02ac89//char类型的指针能够访问1个字节
#include <stdio.h>
//演示实例
int main()
{
int n = 10;
char *pc = (char*)&n;
int *pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc+1);
printf("%p\n", pi);
printf("%p\n", pi+1);
return 0;
}
运行结果如下;
0x16f79ec88
0x16f79ec88
0x16f79ec89
0x16f79ec88
0x16f79ec8c
总结:指针的类型决定了指针向前或者向后走一步有多大(距离)
什么是野指针
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
1、指针未初始化
#include <stdio.h>
int main()
{
int p;//局部变量指针未初始化,默认为随机值
int *p;//局部的指针变量未初始化,就默认为随机值
*p = 20;
return 0;
}
2、指针越界访问
#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;// 就相当于*p=i;p++;
}
return 0;
}
3、指针指向的空间释放
#include <stdio.h>
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();// a变量是局部变量,一旦出括号,空间被释放,尽管通过*p可以找到&a,但是通过&a找到a空间中所存内容是找不不见的;
printf("%d\n",*p);
return 0;
}
如何规避野指针
1.指针初始化
2.小心指针越界
3.当不用指针时,将该指针置为NULL
4.避免返回局部变量的地址
5.指针使用之前检查有效性
#include<stdio.h>
int main()
{
int a =10;
int* pa = &a;// 指针初始化
int*p = NULL; //当不用指针时,初始化指针为NULL,给指针赋值
if(p!=NULL) // 指针使用之前检查指针的有效性
{
*p=20;
}
return 0;
}
指针的运算
1、指针++
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
int* p = arr;
for(i=0; i<sz;i++)
{
printf("%d\n",*p);
p++;
}
return 0;
}
运行结果如下;
1
2
3
4
5
6
7
8
9
10
2、指针+整数
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
int* p = arr;
for(i=0;i<5;i++)
{
printf("%d\n",*p);
p+=2;
}
return 0;
}
运行结果如下;
1
3
5
7
9
3、指针-整数
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
int* p = &arr[9];
// for(i=0; i<sz;i++)
// {
// printf("%d\n",*p);
// p++;
// }
for(i=0;i<5;i++)
{
printf("%d\n",*p);
p-=2;
}
return 0;
}
运行结果如下;
10
8
6
4
2
4、指针-指针
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
printf("%d\n",arr);//1841017248
printf("%d\n",&arr[0]);//1841017248
printf("%d\n",arr[0]);//1
printf("%d\n",&arr[9]);//1841017284
printf("%d\n",&arr[9]-&arr[0]);//9
return 0;
}
运行结果如下;
1841017248
1841017248
1
1841017284
9
#include <stdio.h>
int my_strlen(char* str)
{
char* start = str;
printf("%d\n",start);//打印的是地址,1869214152
printf("%c\n",start[0]);//打印的是存放内容 b
char* end = str;
printf("%d\n",end);//打印的是地址,1869214152
printf("%c\n",*end);//打印的是存放内容 b
while(*end!='\0')
{
end++;
printf("%d\n",end); //打印的是地址,1869214153 1869214154 1869214155
printf("%c\n",*end);//打印的是存放内容 i t
}
return end-start;
}
int main()
{
char arr[]="bit";
int len = my_strlen(arr);
printf("%d\n",len);
return 0;
}
运行结果如下;
1809691080
b
1809691080
b
1809691081
i
1809691082
t
1809691083
指针和数组
当arr作为数组名时,arr和&arr的区别
#include<stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,0};
printf("%p\n",arr);//打印的是数组首元素的地址 0x16d05f1a0
printf("%p\n",arr+1);// 0x16d05f1a4
printf("%p\n",&arr[0]);//打印的是数组首元素的地址 0x16d05f1a0
printf("%p\n",&arr[0]+1);//0x16d05f1a4
printf("%p\n",&arr);//打印的是整个数组的地址 0x16d05f1a0
printf("%p\n",&arr+1);// 0x16d05f1c8
return 0;
}
运行结果如下;
[Running] cd "/Users/yrf/Desktop/c/day_01/" && gcc zhizhen.c -o zhizhen && "/Users/yrf/Desktop/c/day_01/"zhizhen
0x16d05f1a0
0x16d05f1a4
0x16d05f1a0
0x16d05f1a4
0x16d05f1a0
0x16d05f1c8
[Done] exited with code=0 in 1.137 seconds
数组可以通过指针很好的访问;
#include<stdio.h>
int main()
{
int arr[10]={0};
int* p=arr;
int i=0;
for(i=0;i<10;i++)
{
printf("%p=======%p\n",p+i,&arr[i]);
}
return 0;
}
运行结果如下;
[Running] cd "/Users/yrf/Desktop/c/day_01/" && gcc zhizhen.c -o zhizhen && "/Users/yrf/Desktop/c/day_01/"zhizhen
0x16d5831a0=======0x16d5831a0
0x16d5831a4=======0x16d5831a4
0x16d5831a8=======0x16d5831a8
0x16d5831ac=======0x16d5831ac
0x16d5831b0=======0x16d5831b0
0x16d5831b4=======0x16d5831b4
0x16d5831b8=======0x16d5831b8
0x16d5831bc=======0x16d5831bc
0x16d5831c0=======0x16d5831c0
0x16d5831c4=======0x16d5831c4
[Done] exited with code=0 in 0.623 seconds
#include<stdio.h>
int main()
{
int arr[10]={0};
int* p=arr;
int i=0;
for(i=0;i<10;i++)
{
*(p+i)=i;
//printf("%d\n",*(p+i));// 0 1 2 3 4 5 6 7 8 9
printf("%d\n",arr[i]);// 0 1 2 3 4 5 6 7 8 9
}
return 0;
}
运行结果如下;
[Running] cd "/Users/yrf/Desktop/c/day_01/" && gcc zhizhen.c -o zhizhen && "/Users/yrf/Desktop/c/day_01/"zhizhen
0
1
2
3
4
5
6
7
8
9
[Done] exited with code=0 in 0.63 seconds
二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就是二级指针。
#include<stdio.h>
int main()
{
int a=10;
int* p=&a;
int** pa =&p;
printf("%p\n",p);
printf("%d\n",*p);
printf("%p\n",*pa);
printf("%d\n",**pa);
*p=20;
printf("%p\n",p);
printf("%d\n",*p);
printf("%p\n",*pa);
printf("%d\n",**pa);
return 0;
}
[Running] cd "/Users/yrf/Desktop/c/day_01/" && gcc zhizhen.c -o zhizhen && "/Users/yrf/Desktop/c/day_01/"zhizhen
0x16ae2b1c8
10
0x16ae2b1c8
10
0x16ae2b1c8
20
0x16ae2b1c8
20
[Done] exited with code=0 in 0.735 seconds
指针数组
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = 30;
int* arr2[3]={&a,&b,&c};//指针数组 arr2是一个数组,数组中有3个元素,每个元素都是一个整形指针
int i = 0;
for(i=0;i<3;i++)
{
printf("%d\n",*arr2[i]);
}
return 0;
}
运行结果如下;
[Running] cd "/Users/yrf/Desktop/c/day_01/" && gcc zhizhen.c -o zhizhen && "/Users/yrf/Desktop/c/day_01/"zhizhen
10
20
30
[Done] exited with code=0 in 0.44 seconds
#include<stdio.h>
int main()
{
int arr1[] = {1,2,3,4,5};
int arr2[] = {1,3,4,5,6};
int arr3[] = {3,4,5,6,7};
int* parr[] = {arr1,arr2,arr3};
int i = 0;
for(i=0;i<3;i++){
int j = 0;
for(j=0;j<5;j++){
printf("%d",*(parr[i]+j));
}
printf("\n");
}
return 0;
}
[Running] cd "/Users/yrf/Desktop/c/day_01/" && gcc zhizhen.c -o zhizhen && "/Users/yrf/Desktop/c/day_01/"zhizhen
12345
13456
34567
[Done] exited with code=0 in 0.399 seconds