C语言指针详解(初级)

1. 指针是什么?


指针理解的 2 个要点:
        1. 指针是内存中一个最小单元的编号,也就是地址(&)
        2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
总结:指针就是地址,口语中说的指针通常指的是指针变量。
那我们就可以这样理解:
        内存(如图所示):

1.1指针变量

我们可以通过 & (取地址操作符)取出变量的内存起始地址,把地址可以存放到一个变量中,这个
变量就是指针变量
int main() {  int a = 10;//在内存中开辟一块空间  int* p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。  //a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量  //中,p就是一个之指针变量。  return 0; }
总结:
指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。

2. 指针和指针类型

        我们都知道,在c语言中变量有不同的类型,整形,浮点型等。那指针有没有类型呢?
准确的说:有的!
当有这样的代码:
int num = 10 ;
p = & num ;
要将 &num num 的地址)保存到 p 中,我们知道 p 就是一个指针变量,那它的类型是怎样的呢?
我们给指针变量相应的类型。
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 类型变量的地址。
那指针类型的意义是什么?

2.1 指针+-整数

总结: 指针的类型决定了指针向前或者向后走一步有多大(距离)

2.2 指针的解引用

总结
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

3. 野指针

        概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

3.1 野指针成因

        1. 指针未初始化

注意:在vs2022上是打印不出来随机值的,在Dev,小熊猫编译器上可以打印出随机值  知道即可!
        

        2. 指针越界访问

如图所示,超出了数组的范围,就找不到啦!!!

3.2 如何规避野指针

        1. 指针初始化
        2. 小心指针越界
        3. 指针指向空间释放,及时置 NULL
        4. 避免返回局部变量的地址
        5. 指针使用之前检查有效性

4. 指针运算

  • 指针 +- 整数
  • 指针 - 指针
  • 指针的关系运算

4.1 指针+-整数

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

4.2 指针-指针

int my_strlen(char *s)
{
       char *p = s;
       while(*p != '\0' )
              p++;
       return p-s;
}

4.3 指针的关系运算

for(vp = &values[N_VALUES]; vp > &values[0];)
{
    *--vp = 0;
}
代码简化 , 这将代码修改如下:
for ( vp = & values [ N_VALUES - 1 ]; vp >= & values [ 0 ]; vp -- )
{
    * vp = 0 ;
}
        实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证 它可行。
标准规定:
        允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与 指向第一个元素之前的那个内存位置的指针进行比较。

5. 指针和数组

        看一个示例:

看到运算结果,我们可想而知 可见数组名和数组首元素的地址是一样的。
结论 数组名表示的是数组首元素的地址
那么这样写代码是可行的:

int arr [ 10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 };
int * p = arr ;
既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问一个就成为可能。
例如:
#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]);
    for(i=0; i<sz; i++)
   {
        printf("&arr[%d] = %p   <====> p+%d = %p\n", i, &arr[i], i, p+i);
   }
    return 0;
}

运算结果如下:

所以 p+i 其实计算的是数组 arr 下标为 i 的地址。
那我们就可以直接通过指针来访问数组。
如下:

6. 二级指针

        想一个问题: 指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
        想到了嘛?
         这就是 二级指针 !
如图所示:
看图得出, a的地址存放在*pa里面,*pa的地址存放在**ppa中
对于二级指针的运算有:
*ppa 通过对 ppa 中的地址进行解引用,这样找到的是 pa *ppa 其实访问的就是 pa .
int b = 20 ;
* ppa = & b ; // 等价于 pa = &b;
**ppa 先通过 *ppa 找到 pa , 然后对 pa 进行解引用操作: *pa ,那找到的是 a .
** ppa = 30 ;
// 等价于 *pa = 30;
// 等价于 a = 30;
懂?

7. 指针数组

        
 指针数组是指针还是数组?
 答案:是数组。是存放指针的数组。
  数组我们已经知道整形数组,字符数组。
int arr1 [ 5 ];
char arr2 [ 6 ];
那指针数组是怎样的?
         int* arr3 [ 5 ]; // 是什么?
arr3 是一个数组,有五个元素,每个元素是一个整形指针。
数组指针详情待下篇分享!!

本篇文章到此就结束啦!   

小磊在此问候大家  还请各位大佬三连!!!丞退了

  • 21
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值