【C语言初阶】带你轻松掌握指针基础知识完结篇——野指针,指针运算,指针和数组,二级指针

简介: 【C语言初阶】带你轻松掌握指针基础知识完结篇——野指针,指针运算,指针和数组,二级指针

一. 野指针

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

1. 野指针成因

  1. 指针未初始化
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
  *p = 20;
return 0;
}
  1. 指针越界访问
#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;
  }
  1. 指针指向的空间释放
  • 这里放在指针进阶篇中动态内存开辟的时候讲解

2. 如何规避野指针

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

第三种情况的使用例子

#include <stdio.h>
int main()
{
  int *p = NULL;//在使用前先把指针置空防止为释放指针之前指向的空间
  //....
  int a = 10;
  p = &a;
  if(p != NULL)
 {
    *p = 20;
 }
  return 0;
  }

二. 指针运算

1.指针± 整数

#define m 5
float values[m];
float* vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[m];)
{
    *vp++ = 0;//把values数组中每个元素都初始化为0,这里指针++表示地址后移
}

2.指针-指针

//计算字符串的长度
int my_strlen(char *s)
{
   char *p = s;
   while(*p != '\0' )
       p++;
   return p-s;//当p中读取到\0时说明该字符串总长度为此时的地址p-首元素地址s
   }

3.指针的关系运算

for(vp = &values[m]; vp > &values[0];)
{
  *--vp = 0;//由于是前置--,最后会与第一元素之前的元素比较
}
  • 上面这段代码有比较明显的缺点,我们来简化一下。
for(vp = &values[m-1]; vp >= &values[0];vp--)
{
  *vp = 0;
}




  • 实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。
  • 标准规定:
  • 允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

三. 指针和数组


  • 我们先通过一个例子来建立一下数组与指针之间的联系
#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;

900cf98154ff4ae4813a1cc8e6e1696d.png

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

21f6158a159742f4917e24a70082c7e2.png

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


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

四.二级指针

  • 指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
  • 答案不言而喻—— 二级指针 。
int main()
{
    int a = 10;
    int* p = &a;
    int** pa = &p;
    printf("%d\n", a);
    printf("%d\n", *p);
    printf("%d\n", **pa);
    return 0;
}

bd93e3bb8cbc4772b9fccfc536a3d5f2.png

  • 我们可以看出来三者的值是相同的!!
  • 对于二级指针的运算有:
//*pa通过对pa中的地址进行解引用,这样找到的是p ,*pa 其实访问的就是p .
int b = 20;
*pa = &b;//等价于 p = &b;
//**pa 先通过* pa 找到 p, 然后对 p 进行解引用操作:*p ,那找到的是 a .
**pa = 30;
//等价于*p = 30;
//等价于a = 30;

五. 指针数组

  • 指针数组是指针还是数组?
  • 是数组。是存放指针的数组。

数组我们已经知道整形数组,字符数组。

int arr1[5];
char arr2[6];
  • 那指针数组是怎样的?
int* arr3[5];//是什么?


82be226d2eec4a7c867061f3d5b1859c.png

  • 还有一种指针类型叫做数组指针,是指针,这两种情况我都会放在指针进阶篇中介绍。

总结


  • 今天的内容到这里就全部结束了,我们今天把指针基础部分全部介绍完了,其中主要包括野指针的定义以及如何避免,指针运算的几种形式以及指针与数组的关系和二级指针,希望大家把博客中的代码都弄懂哦!
  • 好了,如果你有任何疑问欢迎在评论区或者私信我提出,大家下次再见啦!

新人博主创作不易,如果感觉文章内容对你有所帮助的话不妨三连一下这个新人博主再走呗。你们的支持就是我更新的动力!!!

**(可莉请求你们三连支持一下博主!!!点击下方评论点赞收藏帮帮可莉吧)**



目录
相关文章
|
1月前
|
存储 C语言 C++
【C语言数组】
【C语言数组】
|
15天前
|
存储 编译器 C语言
【C语言基础考研向】09 一维数组
数组是一种有序集合,用于存储相同类型的数据,便于统一操作与管理。例如,将衣柜底层划分为10个格子存放鞋子,便于快速定位。在C语言中,数组定义格式为 `类型说明符数组名[常量表达式];`,如 `int a[10];` 表示定义了一个包含10个整数的数组。数组初始化时可以直接赋值,也可以部分赋值,且数组长度必须固定。数组在内存中连续存储,访问时需注意下标范围,避免越界导致数据异常。数组作为参数传递时,传递的是首地址,修改会影响原数组。
|
15天前
|
存储 C语言
【C语言基础考研向】10 字符数组初始化及传递和scanf 读取字符串
本文介绍了C语言中字符数组的初始化方法及其在函数间传递的注意事项。字符数组初始化有两种方式:逐个字符赋值或整体初始化字符串。实际工作中常用后者,如`char c[10]=&quot;hello&quot;`。示例代码展示了如何初始化及传递字符数组,并解释了为何未正确添加结束符`\0`会导致乱码。此外,还讨论了`scanf`函数读取字符串时忽略空格和回车的特点。
|
18天前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
18天前
|
存储 人工智能 C语言
C语言程序设计核心详解 第六章 数组_一维数组_二维数组_字符数组详解
本章介绍了C语言中的数组概念及应用。数组是一种存储同一类型数据的线性结构,通过下标访问元素。一维数组定义需指定长度,如`int a[10]`,并遵循命名规则。数组元素初始化可使用 `{}`,多余初值补0,少则随机。二维数组扩展了维度,定义形式为`int a[3][4]`,按行优先顺序存储。字符数组用于存储字符串,初始化时需添加结束符`\0`。此外,介绍了字符串处理函数,如`strcat()`、`strcpy()`、`strcmp()` 和 `strlen()`,用于拼接、复制、比较和计算字符串长度。
|
1月前
|
算法 C语言
C语言------数组
这篇文章是关于C语言数组的实训,包括一维数组、二维数组和字符数组的定义、赋值、输入、输出方法,并通过实例代码演示了数组的使用和一些基本算法,如冒泡排序。
C语言------数组
|
1月前
|
存储 编译器 数据处理
【编程秘籍】解锁C语言数组的奥秘:从零开始,深入浅出,带你领略数组的魅力与实战技巧!
【8月更文挑战第22天】数组是C语言中存储同类型元素的基本结构。本文从定义出发,详述数组声明、初始化与访问。示例展示如何声明如`int numbers[5];`的数组,并通过下标访问元素。初始化可在声明时进行,如`int numbers[] = {1,2,3,4,5};`,编译器自动计算大小。初始化时未指定的元素默认为0。通过循环可遍历数组,数组名视为指向首元素的指针,方便传递给函数。多维数组表示矩阵,如`int matrix[3][4];`。动态数组利用`malloc()`分配内存,需用`free()`释放以避免内存泄漏。掌握这些技巧是高效数据处理的基础。
55 2
|
1月前
|
存储 算法 搜索推荐
C语言中数组
C语言中数组
34 0
|
1月前
|
存储 编译器 程序员
【C语言篇】从零带你全面了解数组(超详细)
有时候,数组在创建的时候,我们需要给定⼀些初始值,这种就称为初始化。
|
1月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)