零基础学指针(上)

embedded/2024/11/25 14:51:16/

系列文章目录

🎈 🎈 我的CSDN主页:OTWOL的主页,欢迎!!!👋🏼👋🏼
🎉🎉我的C语言初阶合集:C语言初阶合集,希望能帮到你!!!😍
😍 👋🏼🎉🎊创作不易,欢迎大家留言、点赞加收藏!!! 🥳😁😍


文章目录

  • 系列文章目录
  • 前言
  • 一、内存中变量的存储
  • 二、指针变量的定义和语法
    • (1)指针变量的定义
    • (2)指针变量的语法
  • 三、指针的运算符
    • (1)取地址运算符(&)
    • (2)取值运算符(*)
  • 四、指针变量的运算
    • (1)指针的加减运算
      • (1.1)指针变量加减整数
      • (1.2)指针变量 减 指针变量
    • (2)指针的比较运算
  • 总结


前言

这篇博客是指针系列 的第一篇
将从内存中变量的存储和指针变量的语法和定义,指针的俩个运算符,分别是取值运算符(*)和取地址运算符(&),
然后还会介绍指针变量的运算。


一、内存中变量的存储

在内存中,每个变量都有一个唯一的地址。
当你声明一个变量时,比如int a = 5;,编译器会在内存中为a分配一个空间,并存储值5
同时,a 也有一个内存地址,这个地址可以通过 指针 来访问。

这里的指针是 指针变量 的简称。

  • 例如:

代码如下(示例):

#include<stdio.h>int main()
{//定义一个整型变量 aint a = 5;//输出变量 a的地址printf("&a = %p\n", &a);return 0;
}
  • 结果如图:

  • 内存的分布图(示例)

解释:变量a是整型,在内存中占4个字节(连续的,输出 &a 只会输出首地址);
内存 在分配时是 随机的。(即每次运行时,产生的地址结果是不同的)

注:0X代表的是十六进制数

二、指针变量的定义和语法

(1)指针变量的定义

指针变量是一种特殊的变量,它存储的不是数据本身,而是数据在内存中的地址。
你可以把指针变量想象成一个“箭头”,它指向了内存中存储数据的那个位置。

(2)指针变量的语法

  • 在C语言中,定义指针变量的语法如下:
数据类型 *指针变量名;

1. 数据类型:指针所指向的数据的类型。

比如,如果你有一个指向整数的指针,那么数据类型就是int

2. *:星号表示这是一个指针变量。

3. 指针变量名:你给这个指针变量起的名字,比如pptr等。

  • 例如:

代码如下(示例):

#include <stdio.h>int main() {int a = 10; // 定义一个整数变量 a,并赋值为 10int* p; // 定义一个指向整数的指针变量 pp = &a; // 将变量a的地址赋给指针变量 pprintf("a的值是: %d\n", a); // 输出 a的值printf("a的地址是: %p\n", &a); // 输出 a的地址printf("指针p的值(即a的地址)是: %p\n", p); // 输出指针 p的值,也就是a的地址printf("通过指针p访问a的值是: %d\n", *p); // 通过指针 p访问a的值return 0;
}
  • 结果如图:

三、指针的运算符

(1)取地址运算符(&)

取地址运算符& 用于获取变量的内存地址。

  • 例如:

代码如下(示例):

#include<stdio.h>int main()
{//定义一个整型变量 aint a = 10;int* p; // 声明一个指向 int 的指针变量 pp = &a; // 将变量 a 的地址赋给指针 p//输出变量 a 的地址printf("&a = %p\n", &a);printf("p = %p\n", p);return 0;
}
  • 结果如图:

  • 内存的分布图(示例)

在这里插入图片描述

(2)取值运算符(*)

取值运算符*用于通过指针访问它所指向的内存地址中的值。

  • 例如:

代码如下(示例):

#include<stdio.h>int main()
{//定义一个整型变量 aint a = 10;int* p = &a; // 声明一个指向 int 的指针变量 p,p 指向 a 的地址int b = *p; // 通过指针 p 获取 a 的值,并赋给 b//输出变量a的值printf("a = %d\n", a);//输出变量b的值printf("b = %d\n", b);return 0;
}
  • 结果如图:

四、指针变量的运算

因为指针是一个变量,但它存储的不是普通的数据值,而是另一个变量的内存地址
指针的运算其实就是内存单元(地址)之间的运算
指针的运算主要包括 指针的 加减运算 和 指针的 比较运算

(1)指针的加减运算

(1.1)指针变量加减整数

指针的加减整数运算 实际上是对指针所指向的内存地址进行加减。
由于指针指向的是某种类型的数据,所以加减运算的 步长是这种类型数据的大小。

  • 例如:

代码如下(示例):

#include <stdio.h>int main() {//定义一个整型的一维数组,大小是 5,里面存放着 1,2,3,4,5int a[5] = { 1, 2, 3, 4, 5 };int* p = &a[0]; // p指向数组 a的第一个元素// 指针与整数相加:跳过数组中的元素p = p + 2; // p现在指向arr[2],因为从arr[0]开始加了2个整型类型的大小printf("*p = %d\n", *p); // 输出3// 指针与整数相减:回到之前的元素p = p - 2; // p现在指向arr[0],因为从arr[2]开始减了2个整型类型的大小printf("*p = %d\n", *p); // 输出1return 0;
}
  • 结果如图:

(1.2)指针变量 减 指针变量

当你执行两个指针变量的减法运算时,你实际上是在计算它们所指向的内存地址之间的差值,
但这个差值并不是以字节为单位,而是以指针所指向的数据类型的大小为单位
实际上就是 两个指针之间相隔的元素个数

注意:两个指针变量的减法运算只能在指向同一数组或连续内存块的指针之间进行。
如果两个指针不指向同一数组或连续内存块,
那么减法运算的结果是未定义的, 可能会导致程序崩溃或产生不可预测的行为。

#include <stdio.h>int main() {int arr[5] = { 10, 20, 30, 40, 50 }; // 定义一个整数数组int* p1 = &arr[1]; // 定义一个指向 arr[1]的指针int* p2 = &arr[4]; // 定义一个指向 arr[4]的指针// 计算两个指针之间的差值int dif = p2 - p1; // 这将计算 p2 和 p1 之间相隔的元素个数// 输出结果printf("dif: %d\n", dif);// 输出: dif is: 3// 验证通过指针算术访问数组元素printf("p1: %d\n", *p1); // 输出:p1: 20printf("p1 + dif: %d\n", *(p1 + dif)); // 输出: p1 + dif: 50,这里 p1 + dif 实际上等于 p2return 0;
}
  • 结果如图:

(2)指针的比较运算

指针的比较运算通常用于比较两个指针是否指向 同一个内存地址 或比较 它们在内存中的相对位置。

  • 例如:

代码如下(示例):

#include<stdio.h>int main()
{//定义一个整型变量 a,初始化为 10int a = 10;//定义一个整型变量 b,初始化为 20int b = 20;// 声明一个指向 int 的指针变量 p1,p1 指向 a 的地址int* p1 = &a;	// 声明一个指向 int 的指针变量 p2,p2 指向 b 的地址int* p2 = &b;//判断if (p1 == p2) {// 这两个指针指向不同的地址,所以不会执行这里的代码}else {// 这两个指针指向不同的地址,所以执行这里的代码printf("hehe\n");}return 0;
}
  • 结果如图:

总结

1. 指针是一个变量,用于存储另一个变量的内存地址。

2. 取地址运算符 & 用于获取变量的内存地址。

3. 取值运算符 * 用于通过指针访问它所指向的内存地址中的值。

4. 指针的运算包括加减运算和比较运算,用于操作 指针所指向的内存地址。

5. 指针类型的意义
(1)指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
比如:char*的指针解引用就只能访问一个字节,
int* 的指针解引用能访问四个字节
(2)指针的类型决定了指针向前或者向后走一步有多大(距离)。


每天都在学习的路上!
On The Way Of Learning


http://www.ppmy.cn/embedded/140410.html

相关文章

微信小程序技术架构图

一、视图层1.WXML&#xff08;WeiXin Markup Language&#xff09; 这是微信小程序的标记语言&#xff0c;类似于 HTML。它用于构建小程序的页面结构。例如&#xff0c;通过标签来定义各种视图元素&#xff0c;如<view>&#xff08;类似于 HTML 中的<div>&#xff…

Optional类

0.由来 实际 Java 开发过程中&#xff0c;尝试访问空引用的属性或者调用空引用的方法&#xff0c;会报 空指针异常&#xff08;NullPointerException&#xff09;。处理可能为 null 的值时&#xff0c;需要增加很多 条件判定&#xff0c;比如&#xff1a; &#x1f497;User&…

C语言中的结构体,指针,联合体的使用

目录 1. 概述2. 定义和初始化3. 成员的使用4. 结构体数组5. 结构体套结构体6. 结构体赋值7. 结构体和指针8. 结构体作为函数参数9. 共用体&#xff08;联合体&#xff09;10. typedef就是取别名总结 1. 概述 数组&#xff1a;连续的相同数据类型的集合 结构体&#xff1a;不同…

Java将PDF保存为图片

将 PDF 文件转换为图片是常见的需求之一&#xff0c;特别是在需要将 PDF 内容以图像形式展示或处理时。其中最常用的是 Apache PDFBox。 使用 Apache PDFBox Apache PDFBox 是一个开源的 Java 库&#xff0c;可以用来处理 PDF 文档。它提供了将 PDF 页面转换为图像的功能。 …

SSM--SpringMVC复习(一)

SpringMVC Spring MVC 是一个实现了MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c; 本质上相当于 Servlet&#xff0c;以 DispatcherServlet 为核心&#xff0c;负责协调和组织不同组件以完成请求处理并返回响应。通过控制器&#xff08;C&#xff09;对模型数据&…

十五届蓝桥杯赛题-c/c++ 大学b组

握手问题 很简单&#xff0c;相互牵手即可&#xff0c;但是要注意&#xff0c;第一个人只能与其他49个人牵手&#xff0c;所以开头是加上49 #include <iostream> using namespace std; int main() {int cnt0;for(int i49;i>7;i--){cnti;//cout<<i<<&quo…

第十章 JavaScript的运用

10.1 JavaScript概述 1.JavaScript简介 JavaScript是一种基于对象&#xff08;Object&#xff09;和事件驱动&#xff08;Event Driven&#xff09;并具有安全性能的脚本语言&#xff0c;能够与HTML&#xff08;超文本标记语言&#xff09;、Java语言一起在Web页面中与Web客…

银河麒麟v10 x86架构二进制方式kubeadm+docker+cri-docker搭建k8s集群(证书有效期100年) —— 筑梦之路

环境说明 master&#xff1a;192.168.100.100 node: 192.168.100.101 kubeadm 1.31.2 &#xff08;自编译二进制文件&#xff0c;证书有效期100年&#xff09; 银河麒麟v10 sp2 x86架构 内核版本&#xff1a;5.4.x 编译安装 cgroup v2启用 docker版本&#xff1a;27.x …