C语言基础:初识指针(二)

当你不知道指针变量初始化什么时,可以初始化为空指针

cpp 复制代码
int *p=NULL;

我们看NULL的定义,可以看出NULL是0被强制转化为Void* 类型的0;实质还是个0;


如何避免野指针:

  1. 指针初始化
  2. 小心指针越界
  3. 指针指向空间释放即使置 NULL
  4. 避免返回局部变量的地址
  5. 指针使用之前检查有效性

指针运算

  • 指针+- 整数
  • 指针-指针
  • 指针的关系运算

指针+- 整数

下面这段代码实现的是打印数组的元素。

cpp 复制代码
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *p);
		p = p + 1;
	}
	return 0;
}

指针 - 指针

cpp 复制代码
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", & arr[9] - &arr[0]);
	return 0;
}

指针-指针得到的是中间元素的个数

例如:求字符串的长度。模拟实现strlen这个函数

cpp 复制代码
int my_strlen(char* str)
{
	char* start = str;
	char* end = str;
	while (*end != '\0')
	{
		end++;
	}
	return end - start;
}
int main()
{
	char arr[] = "bit";
	int len = my_strlen(arr);
	printf("%d\n", len);

	return 0;
}

指针与数组

数组名是首元素地址,怎么证明呢?通过下面的代码进行证明

cpp 复制代码
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	return 0;
}

注意:两个例外

1.&arr - &数组名 - 数组名不是首元素地址-数组名表示整个数组 ,所以&数组名取出的是整个数组的地址,

2.sizeof(arr) - sizeof(数组名)-数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小。单位字节

下面的代码我们来看看他们的区别

cpp 复制代码
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	printf("%p\n", arr);
	printf("%p\n", arr+1);

	printf("%p\n", &arr[0]);
	printf("%p\n", &arr[0]+1);

	printf("%p\n", &arr);
	printf("%p\n", &arr + 1);
	return 0;
}

调试代码如下:

前面两个都是地址加4,最后一个加了40,(16进制的运算)

可以看出&arr是整个数组的地址,整个数组的地址加1,是跳过(整型)4*10(元素个数)=40

既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问其中任意一个就成为可能。

看下面的代码:

cpp 复制代码
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
	int* p = arr; //指针存放数组首元素的地址
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("&arr[%d] = %p   <====> p+%d = %p\n", i, &arr[i], i, p + i);
	}
	return 0;
}

可以看出是是一一对应的关系,所以 p+i 其实计算的是数组 arr 下标为i的地址。 那我们就可以直接通过指针来访问数组。

打印数组元素

cpp 复制代码
int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	int* p = arr; //指针存放数组首元素的地址
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
 	}
    for (i = 0; i < sz; i++)
	{
		printf("%d \n", arr[i]);
	}
	return 0;
}

二级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?

所以我们就有二级指针

a 的类型是int

pa 的类型是int*

ppa 的类型是int** 最后一个*表示是指针,指向的对象是int*

cpp 复制代码
int main()
{
	int a = 10;
	int* pa = &a;
	int** ppa = &pa;
	printf("%d\n", **ppa);
}

指针数组

与数组指针的区别 就像好孩子,重点是孩子,

指针数组-数组 --存放指针的数组。

数组指针-指针。

为啥要与指针数组,跟数组的由来一样,看下面的代码,对同一类型的地址存储,如果一个一个写下去,太麻烦了,所以我们要有指针数组来存放,这样就方便多了。

cpp 复制代码
int main()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int* pa = &a;
	int* pb = &b;
	int* pc = &c;
	return 0;
}

怎么初始化呢?

cpp 复制代码
int arr[10];
int* arr1[3];//指针数组初始化

存放的类型都是int* 的类型

cpp 复制代码
int* arr1[3] = { &a,&b,&c };
cpp 复制代码
int main()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int* arr2[3] = { &a,&b,&c };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%d \n", *(arr2[i]));
	}
	return 0;
}
相关推荐
JAVA学习通几秒前
北京明光云振铎数据科技Java面经
java·开发语言·科技
jerryinwuhan6 小时前
基于各城市站点流量的复合功能比较
开发语言·php
迈巴赫车主7 小时前
Java基础:list、set、map一遍过
java·开发语言
南 阳8 小时前
Python从入门到精通day66
开发语言·python
十八旬9 小时前
快速安装ClaudeCode完整指南
开发语言·windows·python·claude
前进的李工9 小时前
EXPLAIN输出格式全解析:JSON、TREE与可视化
开发语言·数据库·mysql·性能优化·explain
Byron Loong10 小时前
【c++】为什么有了dll和.h,还需要包含lib
java·开发语言·c++
Dlrb121110 小时前
C语言-指针数组与数组指针
c语言·数据结构·算法·指针·数组指针·指针数组·二级指针
独隅10 小时前
CodeX + Visual Studio Code 联动的全面指南
开发语言·php
坚果派·白晓明10 小时前
【鸿蒙PC三方库移植适配框架解读系列】第一篇:Lycium C/C++ 三方库适配 — 概述与环境配置
c语言·开发语言·c++·harmonyos·开源鸿蒙·三方库·c/c++三方库