指针——C语言初阶

一.指针基本概念:

  1. 指针是内存中一个最小单元的编号,也就是地址
  2. 平时口语中说的指针,通常指的是指针变量,是用来存放地址的变量
    #include<stdio.h>
    int main()
    {
    	int a = 0;
        //a是整型变量,占用四个字节的内存空间,在内存中开辟一块空间
    	int* pa = &a;
    	printf("%p", pa);
    	//pa是一个指针变量,用来存放地址,这里是将a的四个字节的第一个字节的地址存放在ap变量中
    	return 0;
    }

  3. 指针变量:我们可以通过&(取地址操作符)取出变量的内存真实地址,把地址可以存放到一个变量中这个变量就是指针变量。(存放在指针中的值都被当成地址处理)
  4. 指针变量中存放的是地址,通过这个地址,就可以找到一个内存单元
  5. 指针的大小在32位平台是四个字节,在64位平台是八个字节
  6. x86  - 32位

    x64  - 64位


二.指针和指针类型:

  1. 我们都知道普通变量都有不同的类型,由整型,字符型,浮点型等等,而指针变量也有不同的类型
    int a = 5;
    
    假设有以上a变量,那么我们可以将a的地址储存进以下指针变量中
    
    char* pc = &a;
    
    short* ps = &a;
    
    int* pi = &a;
    
    long* pl = &a;
    
    float* pf = &a;
    
    double* pd = &a;
    
  2. 我们需要注意的是:例如:int*p——指针类型是int*,指针所指向的类型是int。(不要记混)
  3. 既然一个整型类型的数据可以被别的不同类型数据的指针储存,那么指针类型的意义又是什么呢?

(1)指针+-整数:

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

(2)指针的解引用:
#include<stdio.h>
int main()
{
	int n = 0x11223344;
	char* pc = (char*)&n;
	int* pi = &n;
	*pc = 0;//重点在调试的过程中观察内存的变化
	*pi = 0;//重点在调试的过程中观察内存的变化
	return 0;
}

总结:指针类型决定了,对指针解引用的时候有多大权限(能操作几个字节)

比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针解引用就能访问四个字节


三.野指针:

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

(1)野指针成因:
  1. 指针未初始化:
    #include<stdio.h>
    int main()
    {
    	int* p;
    	//p没有初始化,就意味着没有明确的指向
    	//一个局部变量不初始化的话,放的是随机值
    	*p = 10;//非法访问内存了
    	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. 指针指向的空间释放:
    #include<stdio.h>
    int* test()
    {
        int a = 10;
        //a为局部变量,函数开始时创建,函数结束时销毁
        return &a;
    }
    int main()
    {
        int* p = test();
        *p = 20;
        //此时p指向的空间已销毁(被释放),不属于当前程序,此时指针p就为野指针
        return 0;
    }
    

(2)如何规避野指针:
  1. 指针初始化:
  2. 注意指针是否越界
  3. 指针指向被释放空间时置为NULL(空指针)
  4. 指针使用之前应检查其有效性

这里展示几个代码:

比较以下代码,并注意注释的内容:

函数栈帧与销毁:


四.指针运算:

(1)指针+-整数:

总结:

  • 从0位到5位,地址是由低到高的
  • *p++=0;相当于:*p=0   p++  
  • 指针变量的自增自减运算,指针加一或减一运算,表示指针向前或向后移动一个单位(不同类型的指针,单元长度不同 )。这个在数组中非常常用。
    #include<stdio.h>
    int main()
    {
    	int arr[10] = { 0 };
    	int i = 0;
    	int n = sizeof(arr) / sizeof(arr[0]);//计算出数组中元素的个数
    	/*for (i = 0; i < n; i++)
    	{
    		arr[i] = 1;
    	}*/
    	int* p = &arr[0];
    	for (i = 0; i < n; i++)
    	{
    		*p++ = 1;//*(p+i)=1
    	}
    	return 0;
    }

(2)指针-指针:

观察下图:

可以很直观的得出:数组中两个指针相减得到的是指针和指针之间元素的个数

注意:

  • 不是所有指针都能相减
  • 指向同一块空间的两个指针才能相减!

例题:编写函数(不允许创建临时变量),求字符串的长度(三种方法)

  • 循环
  • 递归
  • 指针-指针
//循环
#include<stdio.h>
int my_strlen(char* n)
{
	int count = 0;
	while (*n != '\0')
	{
		count++;
		n++;
	}
	return count;
}
int main()
{
	int len = my_strlen("lover");
	printf("%d", len);
	return 0;
}
//递归
#include<stdio.h>从
int my_strlen(char* n)
{
	if (*n != '\0')
	{
		return 1 + my_strlen(n + 1);
	}
	else
	{
		return 0;
	}
}
int main()
{
	int len = my_strlen("lover");
	printf("%d", len);
	return 0;
}
//指针-指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int my_strlen(char* n)
{
	char* np = n;
	while (*n != '\0')
	{
		n++;
	}
	return n - np;
}
int main()
{
	char arr[] = "study";
	int len = my_strlen(arr);
	printf("%d", len);
	return 0;
}

(3)指针的关系运算:

#include<stdio.h>
#define A 5
int main()
{
	int arr[10] = { 0 };
	int* p = &arr[A];
	for (p = &arr[A]; p > &arr[0];)
	{
		*--p = 0;
	}
	return 0;
}

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


五.指针和数组:

  1. 数组名表示的是数组首元素地址(两种情况除外,数组章节讲了——sizeof,&)

(不必多说,数组那节都已经讲了)


六.二级指针:

二级指针变量用来存放一级指针变量的地址

观察下面代码:

  1. pa是一个指针变量,一级指针
  2. ppa是一个二级指针变量
  3. int*是说明ppa是指针,ppa指向的对象是int*类型


七.指针数组:

指针数组是数组,是存放指针的数组(数组我们已经了解了整型数组,字符数组)

观察下列代码:

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int arr[10];
	int* ap = &a;
	int* bp = &b;
	int* cp = &c;
	//parr是存放指针的数组,就是指针数组
	int* parr[10] = { &a,&b,&c };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%d\n", *(parr[i]));
	}
	return 0;
}

可以用其打印二维数组:

#include<stdio.h>
int main()
{
	int arr1[4] = { 1,2,3,4 };
	int arr2[4] = { 2,3,4,5 };
	int arr3[4] = { 3,4,5,6 };
	int* parr[3] = { &arr1,&arr2,&arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%d", parr[i][j]);//相当于:arri[j]
			//parr[1]相当于arr1,也可以改为 *( *(parr+i)+j)
			//arr[i] <==> *(arr+i)
		printf("\n");
	}
	return 0;
}

知识点:arr[i] <==> *(arr+i)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/158435.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统(CentOS7)上安装MYSQL8.x

Linux系统是CentOS7版本&#xff0c;今天在新电脑上安装MYSQL&#xff0c;跟着网上的文章&#xff0c;尝试了好几次&#xff0c;都是启动失败&#xff0c;删了安&#xff0c;安了删&#xff0c;搞了一下午&#xff0c;头昏脑胀&#xff0c;网上的一些文章太乱了&#xff0c;每种…

SSM框架

SSM SSM框架说明SpringBootMyBatis整合MyBatis数据库中表的设计Pojo对象设计Dao接口设计Dao单元方法进行测试 XML管理整合MyBatis框架映射配置文件的位置XML配置SQL标签常用的SQL标签 动态SQL语句动态删除数据动态修改数据 SSM框架说明 Spring 指 Spring Framework&#xff0c…

前段-用面向对象的方式开发一个水管小鸟的游戏

首先准备好各类空文件 index.js css html 和图片 图片是下面这些&#xff0c;如果没有的可在这里下载 2 开发开始 好了&#xff0c;基础准备工作完毕&#xff0c;开发开始&#xff0c; 首先&#xff0c;先把天空&#xff0c;大地&#xff0c;小鸟的盒子准备好&#xff0c;并…

Redis数据库双写一致性解决方案

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

好用的企业防泄密软件盘点

企业防泄密软件是专门设计用于保护企业敏感信息不被泄露的软件产品。这类软件通常采用多种安全技术和策略&#xff0c;以增强企业数据的安全性和保密性&#xff0c;防止核心知识产权和商业机密的泄露。 企业防泄密软件的主要功能包括数据加密、访问控制、审计和监控、文件和数据…

CSS样式穿透

当我们在vue项目中使用第三方组件时&#xff0c;有时候需要去修改某些元素的样式&#xff0c;但有时写的css样式不会覆盖组件的样式&#xff0c;所以要用到样式穿透。 常用的方法有这几种&#xff1a;&#xff08;1&#xff09;>>> &#xff08;2&#xff09;/deep/ …

flink中配置Rockdb的重要配置项

背景 由于我们在flink中使用了状态比较大&#xff0c;无法完全把状态数据存放到tm的堆内存中&#xff0c;所以我们选择了把状态存放到rockdb上&#xff0c;也就是使用rockdb作为状态后端存储,本文就是简单记录下使用rockdb状态后端存储的几个重要的配置项 使用rockdb状态后端…

电子器件系列44:环形线圈电感

干货&#xff01;电感最重要、最常见的几个作用_线圈 环形线圈电感的原理&#xff1a; 电感中包含了哪三个物理学定律&#xff0c;为什么它能以磁场形式储能_哔哩哔哩_bilibili 电感的基本原理_哔哩哔哩_bilibili 环形线圈电感的作用: 1.储能器&#xff1a; 环形线圈电感能够…

【Python大数据笔记_day10_Hive调优及Hadoop进阶】

hive调优 hive官方配置url: Configuration Properties - Apache Hive - Apache Software Foundation hive命令和参数配置 hive参数配置的意义: 开发Hive应用/调优时&#xff0c;不可避免地需要设定Hive的参数。设定Hive的参数可以调优HQL代码的执行效率&#xff0c;或帮助定位问…

005.存储管理

使用硬盘设备前需要对其进行分区、格式化&#xff0c;分区可以使公司业务数据得到更有效的管理。我们需要提前规划好硬盘的存储空间&#xff0c;至于一块硬盘到底要分多少个区&#xff0c;每个分区预留多大空间&#xff0c;这需要根据文件数量、大小、类型等进行对应的设计。有…

c语言:解决判断两个字符串是不是互为旋转字符的问题

题目&#xff1a; 思路&#xff1a;先判断两个字符长度是否相等&#xff0c;如果不相等&#xff0c;肯定不是互为旋转字符串。 方法一&#xff1a;将第一份字符串右旋0-n&#xff08;字符个数&#xff09;次&#xff0c;判断是否有一次右旋完的字符串等于第二个字符串。如果有&…

MIKE水动力笔记19_统计平均潮差

本文目录 前言Step 1 ArcGIS中创建渔网点Step 2 将dfsu数据提取到渔网点Step 3 Python统计平均潮差 前言 日平均潮差&#xff08;average daily tidal range&#xff09;&#xff1a;日高潮潮高合计之和除以实有高潮个数为日平均高潮潮高&#xff0c;日低潮潮高合计之和除以实…

剑指offer(C++)-JZ39:数组中出现次数超过一半的数字(算法-其他)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 给一个长度为 n 的数组&#xff0c;数组中有一个数字出现的次数超过数组长度的一半&#xff0c;请找出这个…

Taro.navigateTo 使用URL传参数和目标页面参数获取

文章目录 1. Taro.navigateTo 简介2. 通过 URL 传递参数3. 目标页面参数获取4. 拓展与分析4.1 拓展4.2 URL参数的类型4.3 页面间通信 5. 总结 &#x1f389;欢迎来到Java学习路线专栏~Taro.navigateTo 使用URL传参数和目标页面参数获取 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x…

C语言--写一个函数返回bool值,来判断给定的字符串A和B(假设都是小写字母),是否是B中的字符都存在于A中,如果是返回true,否则返回false

一.题目描述 写一个函数返回bool值&#xff0c;来判断给定的字符串A和B&#xff08;假设都是小写字母&#xff09;&#xff0c;是否是B中的字符都存在于A中&#xff0c;如果是返回true&#xff0c;否则返回false。例如&#xff1a; 字符串A&#xff1a;abcde 字符串B&#xff…

搭建yum源并定时同步

一 、安装yum源 1-准备yum目录 cd /data/www/html createrepo -v ./目录 2-安装服务 yum -y install httpd 3-配置服务 /etc/httpd/conf/httpd.conf 4.配置/etc/yum.repo.d/local.rpeo 二、定时更新yum源 #1. 同步整个源到指定目录 [rootV10SP1-1 pac]# reposync -p /root/…

井盖位移监测,智能井盖传感器

在每一个繁华的城市背后&#xff0c;总是有一些默默无闻的英雄。这些英雄或是人或是物&#xff0c;对城市未来建设和城市生命线来讲意义重大。其中井盖作为不可或缺的一部分&#xff0c;默默守护着道路安全与公共安全。它的状态却直接关系到我们的生活便利与安全。近年来随着科…

P2341 [USACO03FALL / HAOI2006] 受欢迎的牛 G

模板记录 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define endl "\n" #define x first #define y second #define int long long using namespace std; typedef long long ll; typedef pair<int, int> …

Arduino项目式编程教学前言

前言–先聊聊我的经历 在停更数年之后&#xff0c;还是打算重新开启Arduino编程教学这一项目&#xff1b;这几年间&#xff0c;我从Arduino编程开发教学&#xff0c;转到C及python教学&#xff0c;又到如今的高中数学教学&#xff0c;跨度竟如此之大&#xff0c;但始终未脱离教…

在通用jar包中引入其他spring boot starter,并在通用jar包中直接配置这些starter的yml相关属性

场景 我在通用jar包中引入 spring-boot-starter-actuator 这样希望引用通用jar的所有服务都可以直接使用 actuator 中的功能&#xff0c; 问题在于&#xff0c;正常情况下&#xff0c;actuator的配置都写在每个项目的yml文件中&#xff0c;这就意味着&#xff0c;虽然每个项目…