学C的第二十五天【指针的进阶(一)】

=========================================================================

相关代码gitee自取C语言学习日记: 加油努力 (gitee.com)

=========================================================================

 接上期

学C的第二十四天【练习:1. 打印菱形;2. 打印自幂数;3. 求Sn=a+aa..n项之和;4. 喝汽水问题;5. 调整数组使奇数位于偶数前面;6. 打印X形图案;7……;8……;9……;10……】_高高的胖子的博客-CSDN博客

 =========================================================================

           

指针回顾:

一些指针相关知识:

            

(1). 指针是个用来存放地址的变量地址唯一标识的一块内存空间

内存划分为一个个的内存单元

每个内存单元有一个独立的编号,编号也称为地址

地址C语言中也被称为指针

指针(地址)需要存储起来,存储到变量中,这个变量被称为指针变量

               

               

(2). 指针(地址)的大小是固定的 4/8(32位操作系统/64位操作系统) 个字节

地址是由物理的电线产生的,

32位机器上,有32根地址线,每根会产生 1 或 0 的电信号

32个 1/0 组成一个二进制序列,将这个二进制序列当作地址

需要32个bit位(4个字节)才能存储这个地址,使用指针变量的大小就是4个字节

同理,在64位机器上,

地址是由64个 1/0 组成的二进制序列,需要64个bit位存储,即8个字节

使用这时指针变量的大小8个字节

               

            

(3). 指针是有类型的,指针的类型 决定了指针加减多少个整数的步长指针解引用操作时的权限

           

(4). 指针的运算指针加减整数指针减指针指针关系运算

             

往期指针相关文章:

学C的第五天(初识指针,内存产生内存单元地址过程,指针函数介绍和其大小;结构体补充)_高高的胖子的博客-CSDN博客

           

学C的第十七天【指针初阶: 1. 指针是什么?;2. 指针和指针类型;3. 野指针;4. 指针运算】_高高的胖子的博客-CSDN博客

            

学C的第十八天【指针初阶:5. 指针和数组、6. 二级指针、7. 指针数组;初识结构体:1. 结构体的声明、2. 结构体成员的访问、3. 结构体传参;练习:3道和整数二进制数相关的练习】_高高的胖子的博客-CSDN博客

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

1.字符指针:

(1). 含义:

字符指针指向字符变量指针存放字符变量的地址指针变量

                

(2). 字符指针的一种写法:存放指针变量

使用 取地址符& 取出字符变量的地址赋给 字符指针

              

(3). 字符指针的另一种写法:存放字符串表达式

实际上就是把 字符串表达式首字符地址(字符串表达式起始地址) 赋给 字符指针

              

这里说到了常量,补充一些关于常量的知识

               

(4). 一道相关笔试题:

           

对应代码:

#include <stdio.h>
int main()
{
	// 创建两个字符数组,一个叫str1,一个叫str2,
	// 只不过两个数组存储的内容相同,两个空间是相互独立的
	char str1[] = "hello world.";
	char str2[] = "hello world.";
	
	// str1数组 和 str2数组 是两个相互独立的空间
	// 所以两者指向的 首元素地址 是不同的
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");


	// 这两个是字符指针,“hello world”是一个常量字符串,不会改变
	// 所以只会为常量字符串开辟一个空间,指针使用时直接指向该字符串地址进行使用
	// 那么 str3 和 str4 应该是指向同一个空间(地址)的
	const char* str3 = "hello world.";
	const char* str4 = "hello world.";
	
	// 只会为常量字符串开辟一个空间,指针使用时直接指向该字符串地址进行使用
	// 那么 str3 和 str4 应该是指向同一个空间(地址)的
	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

               

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

2.指针数组:

(1). 含义:

指针数组一个数组,用于存放指针数组

                 

(2). 实例:

                  

(3). 使用指针数组模拟二维数组:

          

对应代码:

//使用指针数组模拟二维数组:
#include <stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	
	//使用指针数组存放3个数组名(数组首元素地址)
	int* arr[3] = { arr1,arr2,arr3 };

	//通过指针数组里的指针找到指针内容
	int i = 0;
	for (i = 0; i < 3; i++)
		//循环0-3,指针数组的下标0-3
	{
		int j = 0;
		for ( j = 0; j < 5; j++)
			//循环0-5,指针数组里指针内容的下标0-5
		{
			printf("%d ", arr[i][j]);
		}

		printf("\n"); //打印完一行后进行换行
	}

	return 0;
}

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

3.数组指针:

(1). 含义:

数组指针指向数组指针存放的是数组的地址指针变量

                   

例子:

int (*p)[10];

           

解释:

* 先和 结合,说明p是一个指针变量

指向的是 int [10] ,即一个大小为10的整型数组

所以 p 一个指针指向一个数组,叫做数组指针

               

(2). 数组名 对比 &数组名(取数组名地址)

         

数组名表示数组首元素地址,但有两个例外

          

1. sizeof(数组名),这里的数组名表示整个数组
计算整个数组的大小单位字节

           

2. &数组名,这里的数组名也表示整个数组
取出整个数组的地址整个数组的地址也是用数组首元素表示

&数组名 + 1 -- 会跳过整个数组,而不是 arr+1 跳过一个元素

                 

实例:

              

对应代码:

//数组名的理解:
//数组名表示数组首元素地址,但有两个例外
#include <stdio.h>
int main()
{
	int arr[10] = { 0 };

	//证明数组名是首元素地址:
	printf("%p\n", arr); //打印arr的地址
	printf("%p\n", &arr[0]); //打印&arr[0]的地址

	//换行:
	printf("\n");

	//数组名不表示首元素的两种例外:
	//1. sizeof(数组名),这里的数组名表示整个数组
	//	计算整个数组的大小,单位是字节
	printf("%d\n", sizeof(arr));

	//换行:
	printf("\n");

	//2. &数组名,这里的数组名也表示整个数组
	//	取出整个数组的地址
	printf("%p\n", arr); //打印arr的地址 -- int* 类型
	printf("%p\n", arr + 1);

	//换行:
	printf("\n");

	printf("%p\n", &arr[0]); //打印&arr[0]的地址 -- int* 类型
	printf("%p\n", &arr[0] + 1);

	//换行:
	printf("\n");

	printf("%p\n", &arr); //打印&arr的地址 -- int(*)[10]
	printf("%p\n", &arr + 1);


	return 0;
}

             

(3). 数组指针的初始化和使用:

           

1 . 数组指针的初始化:

数组指针指向的是数组,那数组指针中存放的应该是数组的地址

            

实例:

              

 2 . 数组指针的使用:一般在二维(或以上)数组使用

              

(2.1). 对二维数组的补充理解:

二维数组每一行都可以理解为二维数组的一个元素

每一行又是一个一维数组

所以二维数组其实是一维数组的数组

              

(2.2). 二维数组的数组名:

二维数组数组名 也是 二维数组首元素的地址

数组首元素的地址 也是 二维数组第一行的地址

二维数组第一行的地址 是一个 一维数组的地址

可以通过 一维数组的地址 访问 一维数组的内容

         

实例:二维数组传参

            

对应代码:

//在二维数组中使用数组指针进行打印
#include <stdio.h>
void Print(int (*p)[5], int r, int c)
	//因为 二维数组数组名 是一个一维数组地址,
	//所以可以用 数组指针 作为形参
{
	int i = 0;
	for (i = 0; i < r; i++)
		//遍历二维数组的元素
	{
		int j = 0;
		for ( j = 0; j < c; j++)
			//遍历二维数组中每一行的元素
		{
			printf("%d ", *(*(p + i) + j));
			// *(p + i) -- 解引用当前行的首元素
			// 再 +j 向后遍历当前行
		}
		//打印完一行进行换行:
		printf("\n");
	}
}

int main()
{
	//定义一个 三行五列的二维数组:
	int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
	
	//定义一个使用 数组指针 打印二维数组的函数:
	Print(arr, 3, 5);
	//参数:(二维数组名,行数,列数)

	return 0;
}

                

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  

4.数组传参和指针传参:

数组传参形参可以用 数组接收,也可以用 指针接收。)

(1). 一维数组传参:

                

(2). 二维数组传参:

                

指针传参形参只能用 指针接收。)

(3). 一级指针传参:

                

(4). 二级指针传参:

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

5.函数指针:

(1). 含义:

函数指针存放函数地址指针

         

(2). 函数也有地址:

                

(3). 函数指针的初始化和调用:

          

1 . 函数指针的 初始化:

               

2 . 函数指针的 调用:

猜你喜欢

转载自blog.csdn.net/weixin_63176266/article/details/131576435