[C语言]指针初阶

news/2024/11/8 16:45:18/

[C语言]指针初阶

文章目录

  • [C语言]指针初阶
    • 1.指针def:
    • 2.指针变量:
    • 3.指针和内存的关系:
    • 4.指针和指针类型:
      • 4.1指针类型:
    • 5.指针+-整数:
    • 6.指针的解引用:
    • 7.野指针:
      • 7.1成因:
      • 7.2如何规避野指针:
    • 8.指针运算:
      • 8.1指针+-整数:
      • 8.2指针-指针:
      • 8.3指针的关系运算:
    • 9.指针和数组:
      • 9.1数组和指针的关系:
    • 10.指针数组:

📟作者主页:慢热的陕西人

🌴专栏链接: C语言

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

本博客简单介绍了指针的概念和指针的初阶的一些知识

1.指针def:

📣指针就是地址,口语中说的指针通常指的是指针变量

2.指针变量:

📣我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个变量就是指针变量

3.指针和内存的关系:

每一个字节(一个基本的内存单元)都有一个地址,在32位的机器上指针变量的大小就是4个字节,因为32位的二进制数字只能编址:4 GB原理如下:

(2 ^ 32 Byte == 2^32/1024 KB ==2^32 / 1024 / 1024 MB ==2^32/1024/1024/1024 GB == 4 GB) 4 G的空间进行编址。

如果是在64位机器上,指针变量的大小就是8个字节,八个字节的二进制数字可以编址的内存空间大小是32位机器的2的32次方倍;

4.指针和指针类型:

📣指针变量的大小都是相同的,为什么还要分很多种类: 决定了指针类型加减整数,指针类型解引用可以操作的内存空间大小

char  *pc = NULL;
int   *pi = NULL;
short *ps = NULL;
long  *pl = NULL;
float *pf = NULL;
double *pd = NULL;

4.1指针类型:

指针类决定了指针进行解引用操作的时候,访问几个字节(权限)

例如:

char*   //char类型指针每次解引用访问只访问一个字节
int*    //int类型指针每次解引用访问只访问四个字节
double* //double类型指针每次解引用访问只访问八个字节

5.指针±整数:

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

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

6.指针的解引用:

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

//演示实例
#include <stdio.h>
int main()
{int n = 0x11223344;char *pc = (char *)&n;int *pi = &n;*pc = 0;   //重点在调试的过程中观察内存的变化。*pi = 0;   //重点在调试的过程中观察内存的变化。return 0; }

7.野指针:

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

7.1成因:

(1)指针未初始化:

#include <stdio.h>
int main()
{ 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;}return 0; }

(3)指针指向的空间释放;

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

8.指针运算:

  1. 指针± 整数
  2. 指针-指针 //指针+指针不可以(进阶会解释)
  3. 指针的关系运算

8.1指针±整数:

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

8.2指针-指针:

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

8.3指针的关系运算:

📣指针可以比较大小

for(vp = &values[N_VALUES]; vp > &values[0];)
{*--vp = 0; 
}for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--) 
{*vp = 0; 
}

📣标准规定:

允许指向数组元素的指针指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与 **指向第一个元素之前的那个内存位置的指针**进行比较。

9.指针和数组:

9.1数组和指针的关系:

📣不同:

  • 数组和指针不是一个东西
  • 数组能够存放一组数,连续的空间,数组的大小取决于元素个数
  • 指针是一个变量,是存放地址的,4/8个字节

📣联系:

  • 数组名是地址(指针)
  • 数组把首元素的地址,交给一个指针变量后可以通过指针变量来访问数组

指针和数组关系应用示例:

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2G8rdykW-1670991890615)(C:\Users\jason\AppData\Roaming\Typora\typora-user-images\image-20221214122058161.png)]

10.指针数组:

📣def:存放指针的数组;

两种示例:

1.实现多个变量的指针的存储

int main()
{int a = 10;int b = 20;int c = 30;int d = 40;int e = 50;int* arr3[5] = {&a, &b, &c, &d, &e};//存放整型指针的数组int i = 0;for (i = 0; i < 5; i++){printf("%d ", *(arr3[i]));}return 0;
}

2.模拟实现二维数组

int main()
{//用一维数组模拟一个二维数组int arr1[] = { 1,2,3,4,5 };int arr2[] = { 2,3,4,5,6 };int arr3[] = { 3,4,5,6,7 };int arr4[] = { 4,5,6,7,8 };int* arr[4] = {arr1, arr2, arr3, arr4};int i = 0;for (i = 0; i < 4; i++){int j = 0;for (j = 0; j < 5; j++){printf("%d ", *(*(arr+i)+j));}printf("\n");}

到这本篇博客的内容就到此结束了。
如果想要更加深入的了解指针可以关注博主接下来的指针进阶,内容更加丰富和详细!
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正

在这里插入图片描述


http://www.ppmy.cn/news/3545.html

相关文章

windows git

git | 安装 网址 https://git-scm.com/downloads https://gitforwindows.org 教程 Git详细安装教程 git连接github远程仓库 git | 设置用户名 邮箱 打开 Git Bash Here 输入&#xff1a; git config --global user.name ‘用户名’ git config --global user.email ‘邮箱’ …

怎么进行视频配音?建议收藏这些配音方法

最近我的朋友向我求助&#xff0c;他想要自己制作一个视频&#xff0c;但是视频里面有些片段需要配音&#xff0c;可是他又不想用自己的声音来配音。一方面担心容易NG&#xff0c;需要录制很多遍&#xff0c;会浪费较多的时间&#xff1b;另一方面是&#xff0c;如果视频录制和…

[附源码]Node.js计算机毕业设计辅导员班级量化管理系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

理解DDR Part 1

DDR x4 x8 x16 x4 x8 x16 指的上图黑色的chip输出的位宽&#xff0c;正常的DDR bus width 需要64bit&#xff0c;所以 chip width x4 x8 x16 黑色chip数量 16 8 4 上图是最常见的x8&#xff0c;也就有8个黑色的chip颗粒。x16的性能和x8的性能相比怎么样呢? 更差&…

HDLBits练习汇总-12-时序逻辑设计测试--更多电路

rule90&#xff08;一维元胞自动机&#xff09; Rule_90是一个具有有趣属性的一维元胞自动机。 规则很简单。有一个一维单元格数组&#xff08;开或关&#xff09;。在每个时间步长&#xff0c;每个像元的下一个状态是像元的两个当前邻居的异或。下表是更详细地表达此规则的方…

C# 数组及集合

一 数组 声明&#xff1a; int [] a; int [,]b; 分配空间&#xff1a; anew int[5]; bnew int[4,5]; 二 集合类 System.Collections命名空间&#xff1b; 数组列表ArrayList 相当于动态数组&#xff0c;实现IList; 哈希表 Hashtable 相当于键/值的集合&#xff0c;实现IDict…

[ Linux ] 线程控制(线程创建,等待,终止)

在上一篇我们了解了Linux下线程的相关概念。而本篇的主要内容是线程控制。线程控制包括线程的创建&#xff0c;线程的终止&#xff0c;线程等待等问题&#xff0c;以及线程分离和Linux常见线程安全问题。 目录 1.线程控制 1.1POSIX线程库 1.2 创建线程 1.2.1 创建线程编码…

Python函数、类和对象、流程控制语句if-else while的讲解及演示(图文解释 附源码)

一、函数 函数是完成某个功能的代码段&#xff0c;可被其他代码调用&#xff0c;调用的代码可以将数据传递给函数&#xff0c;函数可将对数据的处理结果返回给调用代码。 def mysubt( a, b 0 ): # 定义一个自己的减法函数&#xff0c;第二个参数为默认值为0的默认参数c a -…