什么是指针

什么是指针

百度中指针的概念
指针是内存中最小单元的编号,也就是地址。

什么是指针变量

百度中指针变量的概念

平时口语中的指针,通常指的是指针变量,是用来存放内存地址的变量。
我们可以通过&(取地址操作符)取出变量的内存其实是地址,把地址可以存放到一个变量中,这个变量就是指针变量。

#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;

要将&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 =10int* 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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值