【C语言】入门——指针

目录

​编辑

1.指针是什么

2.指针类型和指针运算

2.1指针+-整数

2.2指针-指针

2.3指针的关系运算

3.野指针

3.1野指针成因

👍指针未初始化:

👍指针越界访问:

👍指针指向空间释放:

3.2如何规避野指针

4.指针和数组

5.二级指针

6.指针数组


1.指针是什么

指针,是C语言中的一个重要概念及其特点,也是C语言比较难的部分。

👍.内存被划分成一个个的内存单元,每个内存单元的大小是1个字节

👍.每个字节的内存单元都有一个编号,这个编号就是地址,地址在C语言中称为指针

👍.地址要存储的话,存放在指针变量中

👍.每个内存单元都有一个唯一的地址来标识

👍.在32位机器上地址的大小是4个字节,所以指针变量的大小也是4个字节同理:在64位机器上地址的大小是8个字节,所以指针变量的大小也是8个字节

总结:指针就是地址,口语中说的指针通常指的是指针变量。

2.指针类型和指针运算

👍变量的创建可以使用不同的类型,而指针也有不同的指针类型

复制代码
char  *pc = NULL;    //字符指针 
int   *pi = NULL;    //整形指针 
short *ps =NULL;    //短整型指针 
long  *pl = NULL;    //长整型指针 
float *pf = NULL;    //单精度浮点型指针
double *pd = NULL;    //双精度浮点型指针 
......

2.1指针+-整数

👍指针类型决定了指针进行解引用操作的时候,访问几个字节

int* 访问4个字节

char* 访问1个字节

short* 访问2个字节

👍指针类型决定了指针+1,-1跳过几个字节:

int* 的指针+1,跳过4个字节;

char* 的指针+1,跳过1个字节;

short* 的指针+1,跳过2个字节;

double* 的指针+1,跳过8个字节

总结:

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

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

复制代码
int main()
{
	int n = 10;
	char* pc = (char*)&n;
	int* pi = &n;

	//打印n的地址
	printf("%p\n", &n);
	
	printf("%p\n", pc);
	printf("%p\n", pc + 1);//打印char型跳过一个字节

	printf("%p\n", pi);
	printf("%p\n", pi + 1);	//打印整型指针跳过4个字节
	//0019FB40
	/*0019FB40
		0019FB41
		0019FB40
		0019FB44*/
	return  0;
}

2.2指针-指针

👍指针-指针的前提:两个指针指向同一块区域,指针类型是相同的;

👍指针-指针得到的是:两个指针之间的元素个数;

(如果是小地址-大地址就是负的元素个数)

复制代码
		int arr[10] = { 0 };
		printf("%d\n", &arr[9] - &arr[0]);	//9
		printf("%d\n", &arr[0] - &arr[9]);	//-9
		//两个指针相减的前提是:指针指向的同一块连续的空间

2.3指针的关系运算

👍标准规定:

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

复制代码
#define N_VALUES 5
float values[N_VALUES];
float *vp;
for (vp = &values[0]; vp < &values[N_VALUES];)
{
     *vp++ = 0; }

3.野指针

3.1野指针成因

👍指针未初始化:

复制代码
int main()
{ 
 	int *p;//局部变量指针未初始化,默认为随机值
    *p = 10;
 	return 0; 
}

👍指针越界访问:

复制代码
int main()
{
    int arr[10] = {0};
    int *p = arr;
    int i = 0;
    for(i=0; i<=20; i++)
   {
        //当指针指向的范围超出数组arr的范围时,p就是野指针
        *(p++) = i;
   }
    return 0;
}

👍指针指向空间释放:

复制代码
int* test()
{
	int num = 15;
	return &num;    //出了函数,这块内存就不属于我们了,还给了系统
}

int main()
{
	int* p = test();
	*p = 5;
	return 0;
}

注:变量num为局部变量,生命周期从创建开始到出test函数结束,test函数调用结束后num会将空间还给操作系统,此时回到主函数p的地址已经被释放,此时p就是野指针。

3.2如何规避野指针

👍 指针初始化

👍 小心指针越界

👍 指针指向空间释放即使置NULL

👍 避免返回局部变量的地址

👍 指针使用之前检查有效性

4.指针和数组

👍 指针就是指针,指针变量就是一个变量,存放的地址,指针变量的大小是4/8

👍 数组就是数组,可以存放一组数,数组的大小是取决于元素的类型和个数

👍 数组的数组名是数组首元素的地址,地址是可以访问指针变量中

通过指针和数组的关系,可以利用指针的解引用访问数组的元素,不使用数组的下标。

复制代码
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}
//输出:1 2 3 4 5 6 7 8 9 10

5.二级指针

指针变量也是变量,是变量就有地址,所以指针变量也可以被指针存储,这个是二级指针。

复制代码
int main()
{
	int a = 10;
	int* pa = &a;        //pa就是指针变量,一级指针变量,表示指针指向的a是int
	int* *ppa = &pa;    //ppa就二级指针,表示pp指向的p的类型是int*
	return 0;
}

同样,也可以通过解引用的方式对其访问。

复制代码
int b = 20;
*ppa = &b;//等价于 pa = &b;

**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a

复制代码
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

6.指针数组

👍指针数组是指针还是数组?

答案:是数组。是存放指针的数组。
👍可以利用指针数组来用一维数组模拟二维数组

复制代码
int main()
{
	//用一维数组模拟一个二维数组
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int arr4[] = { 4,5,6,7,8 };

	int* arr[4] = {arr1, arr2, arr3, arr4};    //用指针数组管理一维数组
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

感谢你看到了这里,以上就是我对C语言指针入门的基本概括,文中不足和需要需要改善的地方望得到指点!感激不尽!!!

相关推荐
毛小茛3 分钟前
芋道管理系统学习——项目结构
java·学习
阿里嘎多学长7 分钟前
2026-01-02 GitHub 热点项目精选
开发语言·程序员·github·代码托管
天远云服16 分钟前
Go语言高并发实战:集成天远手机号码归属地核验API打造高性能风控中台
大数据·开发语言·后端·golang
范纹杉想快点毕业17 分钟前
嵌入式通信核心架构:从状态机、环形队列到多协议融合
linux·运维·c语言·算法·设计模式
北岛寒沫30 分钟前
北京大学国家发展研究院 经济学原理课程笔记(第二十五课 开放宏观基本概念)
经验分享·笔记·学习
网安_秋刀鱼32 分钟前
【java安全】反序列化 - CC1链
java·c语言·安全
2501_9418771337 分钟前
在法兰克福企业级场景中落地零信任安全架构的系统设计与工程实践分享
开发语言·php
leiming61 小时前
c++ QT 开发第二天,用ui按钮点亮实体led
开发语言·qt·ui
2501_941882481 小时前
在开普敦跨区域部署环境中构建高可靠分布式配置中心的设计思路与实现实践
开发语言·c#
一只小小Java1 小时前
Java面试场景高频题
java·开发语言·面试