首页 > 其他分享 >c语言:指针以及指针变量(一)

c语言:指针以及指针变量(一)

时间:2024-10-20 20:19:48浏览次数:10  
标签: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个字节。

指针的传参调用

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

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

指针±整数

#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。

标签:return,语言,int,地址,指针,变量,字节
From: https://blog.csdn.net/2401_88035751/article/details/143067326

相关文章

  • 指针(二):数组指针巧妙玩法
    目录数组名的理解数组地址与数组首元素地址区别指针访问数组冒泡排序二级指针指针数组指针数组模拟二维数组数组名的理解在介绍数组指针之前先通过一段代码了解一下数组名的本质是什么。#include<stdio.h>intmain(){ intarr[]={1,2,3,4,5}; int*p1=......
  • C语言深入理解指针笔记(3)
    1.字符指针变量 我们已经了解的指针变量类型有:整形指针变量:int*pint:存放的是整型变量的地址浮点型指针变量:float*pf:存放的是浮点型变量的地址类比可知:char*pc:字符型指针变量:存放的是字符型变量的地址,指向字符型的数据 首先,字符型指针变量的使用有两种方法:......
  • 在运维领域,为什么以文件形式存储密码比环境变量存储密码要更安全?
    dockercomposesecretshttps://docs.docker.com/compose/how-tos/use-secrets/Asecretisanypieceofdata,suchasapassword,certificate,orAPIkey,thatshouldn’tbetransmittedoveranetworkorstoredunencryptedinaDockerfileorinyourapplicat......
  • 数据类型与变量
    1.字面常量在HelloWorld程序中,System.Out.println("HelloWorld");语句,不论程序何时运行,输出的都是HelloWorld,其实"HelloWorld"就是字面常量。常量即程序运行期间,固定不变的量称为常量,比如:一个礼拜七天,一年12个月等。publicclassDemo{  publicstaticvoidmain(......
  • C语言笔记21 字符串
    字符数组charword[]={'H','e','l','l','o','!'};word[0]Hword[1]eword[2]lword[3]lword[4]oword[5]!这不是C语言的字符串,只是字符数组,不能用字符串的方式做计算字符串charword[]={'H','e','l','l&......
  • [包教包会]C语言:详解分支语句(if , switch , goto)和循环语句(while , for , do while
    概览控制语句用于控制程序的执行流程,以实现程序的各种结构方式C语言支持三种结构:顺序结构、选择结构(分支)、循环结构:(其实显示中的事件也都是由这三者混合合成的)它们由特定的语句定义符组成,C语言有九种控制语句。可分成以下三类:1.条件判断语句也叫分支语句:if语句......
  • 二,Java中常量与变量的理解
    Java编程基础:深入理解常量、进制转换与补码在Java编程中,常量、进制转换和补码是理解数据表示和处理的基础。本文将详细探讨这些概念,包括常量的分类、进制转换的方法以及补码的计算。常量常量是在Java程序运行过程中其值不能发生改变的量。它们用于定义固定的值,如配置参数、固定......
  • 【风电功率预测】【多变量输入单步预测】基于VMD-CNN-LSTM的风电功率预测研究(Matlab代
                      ......
  • R语言 S4类
    1S4类S4类是R语言中一种更为严格和复杂的面向对象编程方式。与更简单的S3类相比,S4类提供了更高的灵活性和严格性,适用于需要明确结构的复杂数据和应用场景。更为详细的介绍:https://www.jianshu.com/p/dd181f0698a71.1S4类的主要特点严格的数据类型检查:在S4类中,每个对象的属......
  • 【C语言】指针进阶【万字详细版】
    ㊙️小明博客主页:➡️敲键盘的小明㊙️✅关注小明了解更多知识☝️文章目录前言一、字符指针二、指针数组三、数组指针3.1数组指针的定义3.2数组名和&数组名3.3数组指针的使用四、数组参数、指针参数4.1—维数组传参4.2二维数组传参4.3一级指针传参4.4二级指针......