首页 > 其他分享 >指针以及指针变量(一)(整形、字符)

指针以及指针变量(一)(整形、字符)

时间:2024-08-23 17:55:54浏览次数:9  
标签:字符 return 变量 int 地址 字节 整形 指针

今天简单介绍一些关于指针的知识,达到对指针的初步了解。
因为数组跟函数的指针稍微有些杂乱,今天写介绍关于整形与字符的。函数与数组的会在整理好后一一价绍。

地址

地址也就是我们常说的指针,在讲解指针前先讲个生活中的小例子吧。
学生小明是个住校生,他的朋友来他的学校找他出去玩,通过同学得知小明正在宿舍休息,要是没有宿舍的楼号以及宿舍的房间号,那想找到他就需要在宿舍里一间一间找,会花费大量时间,但是有了楼号跟宿舍编号,那就可以节省很多很多时间。
在编程里这个楼号跟宿舍编号就是我们说的指针了,在电脑里,内存被分为了一个一个小单元,一个单元的大小为一个字节。
内存大小单位如下
bit - ⽐特位
Byte - 字节
KB
MB
GB
TB
PB
1Byte = 8bit
1KB = 1024Byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB
这每一个字节就相当于宿舍编号,我们在编程时把数据放在单元块里,我们通过单元的地址就可以快速准确的找到我们需要的变量了。

关于地址的一些操作符

在简单了解了地址之后,先介绍一些与指针有关的操作符,这些是用指针进行编程时常用的操作符。

取地址操作符 &

在编程时创建的一些变量就是向内存申请了一些空间来存储这些变量。那我们怎么能知道变量的地址呢,就需要“&”这个操作符。
使用案例:

#include<stdio.h>
int main()
{
	int a = 20;
	int* n = &a;//int* 代表n是一个整形类型的指针变量
	return 0;
}

如图,经过调试可以看出我们将a的地址存放到了n里面。
在这里插入图片描述
注:
取地址操作符取出来的是变量的首地址也就是第一个字节的地址,但整形有4个字节,我们用首地址来找寻变量时,电脑会顺着这个首地址找寻n个字节,这个n与指针的类型有关,整形变量的指针就找四个字节,字符类型的就是首地址一个字节。

解引用操作符 *

前面说了取地址操作符,将地址存储到一个变量,那我们直接使用这个变量才操作的话就是使用里面的地址来进行操作。
比如:a+1

#include<stdio.h>
int main()
{
	int a = 20;
	int* n = &a;
	printf("%d", n+1);
	return 0;
}

如图结果是一段乱码,原因是直接使用n变量本质上是让n存放的地址加1,里面存放的其实还是一个地址,然后用“%d”打印,就会使变量类型不符,出现乱码,那么想要正确打印可以用“%p”打印,不过打印出来的也是地址。
在这里插入图片描述
修正后:

#include<stdio.h>
int main()
{
	int a = 20;
	int* n = &a;
	printf("%d", *n+1);//这里在n前面加了个*,对n解引用
	return 0;
}

运行结果正确
在这里插入图片描述
也就是说我们将一个变量a的地址传给另一个变量n时,我们想通过n找到a就需要在前面加一个“*”,它的作用是通过n里面的地址来找到地址里存放的数据。

这两个操作符在指针的应用里经常使用,一定要掌握。

指针变量

整形指针变量:int* p
字符指针变量:char* p
"*"代表变量p是一个指针变量。
int、char表示指针指向的数据类型是整形或者字符。
指针变量大小:
在32位的环境下指针变量大小是4个字节。
在64位的环境下指针变量大小是8个字节。

指针±整数

#include <stdio.h>
int main()
{
	int n = 10;
	char* pc = (char*)&n;//将地址强制转换成char* 类型
	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;
}

运行结果如下:(地址是以16进制显示的)
第一、二、四行都是打印的n的地址,主要观察第三行与第五行。
第三行是pc+1,可以看出它有“012FFB7C”变成了“012FFB7D”,也就是加了个1,但是第五行加了个四,但程序上都是+1,这是为什么?
主要是因为pc是char* 类型的指针变量,让它+1是根据指向变量的数据类型大小来计算的,char类型的变量大小是1,它的地址在加1时也就只是加了一个字节,而int类型的则是加4个字节。
在这里插入图片描述

结论: 指针的类型决定了指针向前或者向后⾛⼀步有多⼤(距离)。

void*指针

在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为⽆具体类型的指针(或者叫泛型指针),这种类型的指针可以⽤来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进⾏指针的±整数和解引⽤的运算。
当我们用一个int* 的指针变量存放char* 类型的指针时,系统会报错,因为类型不兼容,但void* 可以不会有这个问题,不管是字符还是整形甚至是数组函数类型的都可以用它来存放。

指针-指针

我们直到有一个函数叫做strlen,它的作用是求字符串长度。其实本质上也可以理解为用末地址(\0的地址)减首地址求中间有几个字节,也就是指针-指针。

#include <stdio.h>
#include<string.h>
int my_strlen(char* s)
{
	char* p = s;//首地址暂存
	while (*p != '\0')//当遇到\0时跳出循环,这个时候p里面存的就是\0的地址
		p++;
	return p - s;
}
int main()
{
	char arr[] = { "abc" };
	printf("%d\n", strlen(arr));
	printf("%d\n", my_strlen(arr));
	return 0;
}

如图用指针-指针定义的函数与库函数strlen效果一样。
在这里插入图片描述

野指针

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

野指针成因

指针为初始化
#include <stdio.h>
int main()
{ 
 int *p;//局部变量指针未初始化,默认为随机值
 *p = 20;
 return 0;
}
指针越界访问
#include <stdio.h>
int main()
{
 int arr[10] = {0};
 int *p = &arr[0];
 int i = 0;
 for(i=0; i<=11; i++)
 {
 //当指针指向的范围超出数组arr的范围时,p就是野指针 *(p++) = i;
 }
 return 0;
}
指针指向的空间被释放
#include <stdio.h>
int* test()
{
	int n = 100;
	return &n;
}
int main()
{
	int* p = test();
	printf("%d\n", *p);
	return 0;
}

前两个编译时都会报错,但这段代码编译时不会报错,但生成解放方案时会显示一些问题。
正常情况时这样的:
在这里插入图片描述
而它的时这样:可能后面在进行一些操作后会出现报错。
在这里插入图片描述

防止出现野指针

1.对指针进行初始化,也就是给指针赋值一个空指针NULL。
2.小心指针在存放数组地址时越界。
3.不要放置局部变量的地址。
4.指针变量不再使用时及时赋值NULL。

指针的传参调用

当指针变量作为参数进行传参调用时,定义的函数()内部也应该是类型相同指针变量。

void init(int* x)//定义了一个整形指针来接收变量b
{
printf("%d",*x);
}
int main()
{
int n=0;
int* b =&n;
init(b);
return 0;
}

___________________分割符
本次对指针的介绍就结束了。
有错请在评论区指正,谢谢。

标签:字符,return,变量,int,地址,字节,整形,指针
From: https://blog.csdn.net/qq_71391318/article/details/141463312

相关文章

  • C/C++语言基础--字符串(包括字符串与字符数组、字符串与指针、字符串处理函数等),代码
    本专栏目的更新C/C++的基础语法,包括C++的一些新特性前言无论什么语言,字符串都是最重要、最基础的数据类型,他对二进制有很好的对应关系在C语言中没有提供专门的处理字符串的类型,但是我们可以通过字符数组、开辟内存地址来处理字符串本文将从字符串与字符数组的关系、字符......
  • 字符串搜索算法
    目录二分搜索(适用于有序字符串数组)Trie树(前缀树)后缀树与后缀数组二分搜索(适用于有序字符串数组)基本概念二分搜索(BinarySearch)是一种高效的查找算法,适用于在有序数组中查找特定元素。与线性搜索相比,二分搜索通过逐步减少搜索范围,大幅提高查找效率。算法步骤确定中间元......
  • 虚函数返回自己类型指针或引用,重写时返回类型可以不一样
    C++#include<functional>#include<iostream>#include<vector>#include<memory>#include<set>#include<map>#include<string>usingnamespacestd;namespace{/*C++类不能继承它自己*/classAnimal/*:public......
  • C:每日一题:双指针法的使用
    前言:思虑再三,觉得如果有时间每日一题还是可以更新一下的。题目难度:基础解题方法:双指针法一、题目输入一个整数数组,实现一个函数来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。二、题目分析本题目标:将给定的整数数组中......
  • 3.1 string(字符串)
    4.1.string(字符串)SET/SETEX/MSET/MSETNXGET/MGETGETSETINCR/DECRDEL1.设置键值set设置的数据没有额外操作时,是不会过期的。setkeyvalue设置键为name值为yuan的数据setnameyuansetnamerain#一个变量可以设置多次注意:redis中的所有数据操作,如果设置的......
  • I/O(输入/输出)——字节流和字符流
    一、字节流    在计算机中,无论是文本、图片、音频还是视频,所有文件都是以二进制的形式(也就是字节)存在的。为字节的输入输出流提供的一系列流统称为字节流。在JDK中提供了两个抽象类InputStream和OutputStream,它们是字节流的顶级父类。1.InputStream    Inpu......
  • C/C++语言基础--指针三大专题详解3,完结篇(包括指针做函数参数,函数指针,回调函数,左右法
    本专栏目的更新C/C++的基础语法,包括C++的一些新特性前言指针是C/C++的灵魂,和内存地址相关联,运行的时候速度快,但是同时也有很多细节和规范要注意的,毕竟内存泄漏是很恐怖的指针打算分三篇文章进行讲解,本专题是三,完结篇,介绍了指针做函数参数,函数指针,回调函数,左右法则解决复......
  • Latex引用两个文献——使用连字符
    Latex引用两个文献——使用连字符问题描述解决办法问题描述在一些国内期刊正文中引用参考文献时,如果是2个或者2个以上的连续数字时应该用连字符连起来,例如:“[1,3]”,“[4-5]”,但是使用常见的方法(\usepackage[numbers,sort&compress]{natbib})并不会对2个文献引用起作用......
  • Java 字符串转换成罗马数字
    键盘录入一个字符串要求1:长度为小于等于9要求2:只能是数字将内容变成罗马数字下面是阿拉伯数字跟罗马数字的对比关系Ⅰ-1,Ⅱ-2,Ⅲ-3,Ⅳ-4,Ⅴ-5,Ⅵ-6,Ⅶ-7,Ⅷ-8,Ⅸ-9注意点:罗马数字里面是没有0的如果键盘录入的数字包含0,可以变成""(长度为0的字符串)packagetest;......
  • day8字符串:344.反转字符串|541. 反转字符串II|卡码网:54.替换数字
    344.ReverseStringclassSolution{//extrao1spacepublicvoidreverseString(char[]s){intleft=0;intright=s.length-1;while(left<right){chartemp=s[left];s[left]=s[right];......