【C语言】指针-初级

瞳绣的博客

         每天进步一点点,希望的火苗不熄灭。


 

目录

 一、指针是什么?

 二、指针的大小

 三、指针和指针类型

四、指针类型的意义

1.指针+-整数

2.指针的解引用

五、野指针

1.野指针成因

2.如何规避野指针

六、指针运算

1.指针+-整数

2.指针-指针

七、指针和数组

八、二级指针

九、指针数组


一、指针是什么?

指针:指针是个变量,存放内存单元的地址(编号),内存单元是一字节一字节划分的。 在计算机科学中,指针 Pointer )是编程语言中的一个对象,利用地址,它的值直接(points to )存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“ 指针 。意思是通过它能找到以它为地址的 内存单元
#include <stdio.h>
int main()
{
     int a = 10;//在内存中开辟一块空间
     int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
                 //将a的地址存放在p变量中,p就是一个之指针变量。
     return 0;
}
总结:指针就是变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。

 二、指针的大小

32位的机器上 ,地址是 32 0 或者 1 组成二进制序列,那地址就得用 4 个字节的空间来储,所以一个指针变量的大小就应该是 4个字节
如果在 64位机器上 ,如果有 64 个地址线,那一个指针变量的大小是 8个字节 ,才能存放一个地址。

 三、指针和指针类型

 我们都知道,变量有不同的类型,例如整形,浮点型等。其实指针也是有类型的。

//将&num(num的地址)保存到p中,我们知道p其实是一个(int *)类型的指针变量。
int num = 10;
p = &num;
指针类型举例:
char  *pc = NULL;
int   *pi = NULL;
short *ps = NULL;
long  *pl = NULL;
float *pf = NULL;
double *pd = NULL;

这里可以看到,指针的定义方式是:

type + *

其实:char* 类型的指针是为了存放 char 类型变量的地址。short* 类型的指针是为了存放short类型变量的地址。int* 类型的指针是为了存放int类型变量的地址。


四、指针类型的意义

1.指针+-整数

#include <stdio.h>
//演示实例
int main()
{
 int n = 10;
 char *pc = (char*)&n;
 int *pi = &n;
 
 printf("%p\n", &n);    //n的地址(4字节)
 printf("%p\n", pc);    //n的首字节地址(4字节中的第一个字节地址)
 printf("%p\n", pc+1);    //n的第二个字节地址(4字节中的第二个字节地址)
 printf("%p\n", pi);    //n的地址
 printf("%p\n", pi+1);    //n的地址+4字节
 return  0;
}
总结:指针的类型决定了指针向前或者向后走一步有多大(距离)。

2.指针的解引用

//演示实例
#include <stdio.h>
int main()
{
     int n = 0x11223344;
     char *pc = (char *)&n;
     int *pi = &n;
     *pc = 0;   //0x11223300    小端存储
     *pi = 0;   //0x00000000
     return 0;
}
总结:
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

五、野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的。

1.野指针成因

  • 指针未初始化
#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;
}
  • 指针指向的空间释放

这部分的内容在动态内存开辟的时候已经整理过了。

【C语言】动态内存管理_瞳绣的博客-CSDN博客

2.如何规避野指针

  • 指针初始化
  • 小心指针越界
  • 指针指向空间释放即使置NULL
  • 指针使用之前检查有效性
#include <stdio.h>
int main()
{
    int *p = NULL;
    //....
    int a = 10;
    p = &a;
    if(p != NULL)
   {
        *p = 20;
   }
    return 0;
}

六、指针运算

1.指针+-整数

#define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)
{
     *vp++ = 0;
}

总结:指针向后移动的字节数(不同的指针类型向后移动的字节数不同)。

2.指针-指针

int my_strlen(char *s)
{
       char *p = s;
       while(*p != '\0' )
              p++;
       return p-s;
}
for(vp = &values[N_VALUES]; vp > &values[0];)
{
    *--vp = 0;
}

总结:两个指针之间包含的元素个数(注意不是字节数)。


七、指针和数组

1. 数组名表示的是数组首元素的地址
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;//p存放的是数组首元素的地址

2. 我们可以直接通过指针来访问数组。

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));    //通过指针*(p+i)来访问
     }
     return 0;
}

八、二级指针

二级指针: 也是一个变量,变量里面存放的是一级指针的地址。
int a=10;        //a为一个变量;
int* pa=&a;      //pa为一个一级指针
int** ppa=&pa;   //ppa为一个二级指针

我们也可以通过二级指针来修改变量的内容。

*pa=20;    //通过一级指针pa将a的内容修改为20
**ppa=30;    //通过二级指针ppa将a的内容修改为30

九、指针数组

指针数组: 指针数组是一个数组,是存放指针的数组。
数组我们已经知道整形数组,字符数组。
int arr1[5];
char arr2[6];

int* arr3[5];    
//arr3是一个数组,有五个元素,每个元素是一个整形指针。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瞳绣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值