C语言中的指针初阶详解

 更新时间:2025年04月27日 09:29:47   作者:s_little_monster_  
这篇文章主要介绍了C语言中的指针初阶,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、指针的解释

通俗来讲就是某一数据的位置。因为数据的存储是需要空间的,这个空间会有一个地址,指针就是用来存放这个地址的,以便于后续快速的访问

二、指针变量和地址

1、取地址操作符

在C语言中创建变量就是向内存申请空间

#include <stdio.h>
int main()
{
 int a = 10;
 return 0;
}

我们在内存里可以看到在创建变量a的时候申请了一块空间

我们取地址a之后将地址四行显示,发现a存储在了这个地址里,0a就是十六进制下的10

这里我们介绍一下我们的老朋友,&操作符。在以前的学习中,我们在学习scanf函数的时候接触过这个操作符,这个操作符就叫做取地址操作符。

&a取出的是a所占的四个字节中地址最小的字节的地址,通过计算机的一套算法,它懂得这个数据是整形,会取出剩下的三个地址

(这时候我们对scanf函数的理解也会深一个层次

scanf("%d",&a);

这里的&a就是取出a的地址,将里边的值进行修改)

2、指针变量和解引用操作

1、指针变量

那我们通过取地址操作符(&)拿到的地址是⼀个数值,这个数值有时候需要存储起来,⽅便后期再使⽤,我们会把这样的地址值存放在指针变量中。

#include <stido.h>
int main()
{
    int a = 10;
    int *pa = &a;//这样就把取出的a的地址存放到指针pa中了
    return 0;
}

指针变量也是变量,专门用来存放地址,存放在其中的值都会被认为是地址

2、拆解指针类型

    int a = 10;
    int *pa = &a;

*说明pa是指针变量,int 说明pa这个指针变量指向的是一个int类型也就是整型类型的对象

当然如果是short类型的对象那么就

short i = 10;
short *pi = &i;

char类型那么就

char j = 10;
char * pj = &j;

3、解引用操作符

#include <stido.h>
int main()
{
    int a = 10;
    int *pa = &a;
    *pa = 20;
    return 0;
}

这样就把a的值更改为20了

4、注意事项

int*pa
int *pa
int* pa
int * pa

这几个是一样的,表达上没有任何的区别

3、指针变量的大小

#include <stdio.h>
int main()
{
 printf("%zd\n", sizeof(char *));
 printf("%zd\n", sizeof(short *));
 printf("%zd\n", sizeof(int *));
 printf("%zd\n", sizeof(double *));
 return 0;
}

指针变量的大小取决于地址的大小,指针变量的大小和类型是无关,只要指针类型的变量在相同的平台下,大小都是相同的

4、指针的解引用

#include <stdio.h>
int main()
{
 int n = 0x12345678;
 int *pi = &n; 
 *pi = 0; 
 printf("%d",n):
 return 0;
}
#include <stdio.h>
int main()
{
 int n = 0x12345678;
 char *pi =(char*) &n; //强制转化,不然是不可以用char类型的指针来接受int类型的变量的
 *pi = 0; 
 printf("%d",n);
 return 0;
}
  • 第一个运行结果

  • 第二个的运行结果

这说明char类型和int类型的访问权限不同,char类型可以访问一个字节,也就是十六进制下的两位数,int类型可以访问四个字节,也就是十六进制下的八位数

5、void*指针

无具体类型的指针,也叫泛型指针,可以接受任何类型的地址但它不能够进行解引用操作,以及指针±整数的运算(下面来说)

三、指针的运算

1、指针±整数

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));//p+i 这⾥就是指针+整数
	}
	return 0;
}

这里的指针经过加减后是通过单位进行访问的,也就是如果是int类型,那么指针就加了四个字节,char加一个字节,short加两个字节。

2、指针 - 指针

#include <stdio.h>
int my_strlen(char* s)
{
	char* p = s;
	while (*p != '\0')// \0 之前的元素为字符串中的元素
		p++;
	return p - s;
}
int main()
{
	printf("%d\n", my_strlen("abc"));
	return 0;
}

这样就可以算出字符串中的元素个数

3、指针的关系运算

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	while (p < arr + sz) //指针的⼤⼩⽐较
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}

四、野指针

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[0];
	int i = 0;
	for (i = 0; i <= 11; i++)
	{
		//当指针指向的范围超出数组arr的范围时,p就是野指针
		*(p++) = i;
	}
	return 0;
}

3、指针指向的空间释放

#include <stdio.h>
int* test()
{
	int n = 100;
	return &n;
}
int main()
{
	int* p = test();
	printf("%d\n", *p);
	return 0;
}

这些原因其实都很常见,也很有规矩,看一下就能看出来是理所应当的,没啥需要解释的

想办法规避它们就行了

五、const 修饰指针

1、const修饰变量

#include <stdio.h>
int main()
{
	int m = 0;
	m = 20;//m是可以修改的
	const int n = 0;
	n = 20;//n是不能被修改的
	return 0;
}

被const修饰的变量是不能修改的

2、const修饰指针变量

int * p;//没有const修饰
const int * p;//const 放在*的左边做修饰
int const * p;//const 放在*的左边做修饰
int * const p;//const 放在*的右边做修饰

第二行和第三行实际是一样的。

我的理解是看const修饰的量,被其修饰的量是不能改变的,我们先来看第二行和第三行代码,*p不能改变,*p是变量值,也就是指针指向的那个变量的内容,它是不能够改变的,但p也就是地址,指针本身,是可以改变的。

第四行代码,const修饰p,地址,指针本身,是不能改变的,但指针指向的变量的内容是不能改变的

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • c++传递函数指针和bind的示例

    c++传递函数指针和bind的示例

    这篇文章主要介绍了c++传递函数指针和bind的示例,需要的朋友可以参考下
    2014-05-05
  • C++使用ifstream读取文件内容的示例详解

    C++使用ifstream读取文件内容的示例详解

    这篇文章主要为大家详细介绍了C++如何使用ifstream读取文件内容的功能,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的可以了解一下
    2023-03-03
  • 在Qt中使用OpenGL绘制三角形指南

    在Qt中使用OpenGL绘制三角形指南

    在高性能渲染场景中,CPU资源常被过度消耗,导致界面卡顿,而OpenGL作为业界标准的图形API,能通过GPU硬件加速显著降低CPU负载,本文将以绘制三角形为例,教你如何通过Qt的QOpenGLWidget和QOpenGLFunctions实现跨平台GPU渲染,感兴趣的朋友一起看看吧
    2025-04-04
  • QT实现读写ini文件的示例代码

    QT实现读写ini文件的示例代码

    .ini文件是Initialization File的缩写,即初始化文件,本文主要给大家介绍了关于Qt读写ini文件的相关方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-07-07
  • 使用C/C++访问MySQL的教程详解

    使用C/C++访问MySQL的教程详解

    在实际开发中,语言连接MySQL是为了能够在编程语言中与MySQL数据库进行交互和操作,大部分情况我们都是通过语言连接MySQL,建立与MySQL数据库的连接,本篇文章主要讲解使用C/C++访问MySQL的教程,需要的朋友可以参考下
    2024-08-08
  • 详解C++中的ANSI与Unicode和UTF8三种字符编码基本原理与相互转换

    详解C++中的ANSI与Unicode和UTF8三种字符编码基本原理与相互转换

    在C++编程中,我们有时需要去处理字符串编码的相关问题,常见的字符编码有ANSI窄字节编码、Unicode宽字节编码及UTF8可变长编码。很多人在处理字符串编码问题时都会有疑惑,即便是有多年工作经验的朋友也可能搞不清楚。所以有必要讲一下这三种字符编码以及如何去使用它们
    2021-11-11
  • C++中STL容器的主要使用及含义说明

    C++中STL容器的主要使用及含义说明

    这篇文章主要介绍了C++中STL容器的主要使用及含义说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C++中的Lambda表达式及表达式语句

    C++中的Lambda表达式及表达式语句

    这篇文章主要介绍了C++中的Lambda表达式及表达式语句,表达式这个概念在C++中属于比较细节的知识了,很多时候我们只用知道怎么用,对于编译器内部怎么处理我们并不关心;并且关于左值和右值这个概念,也是C++比较深的一个小知识点,需要的朋友可以参考一下
    2021-12-12
  • 深入解析C++和JAVA的字符串

    深入解析C++和JAVA的字符串

    这篇文章主要介绍了C++和JAVA的字符串,JAVA 中String 和StringBuffer的区别,需要的朋友可以参考下
    2015-07-07
  • C++贪心算法实现马踏棋盘

    C++贪心算法实现马踏棋盘

    这篇文章主要为大家详细介绍了C++贪心算法实现马踏棋盘,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02

最新评论