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

相关代码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 int main(){// 创建两个字符数组,一个叫str1,一个叫str2,// 只不过两个数组存储的内容相同,两个空间是相互独立的char str1[] = "hello world.";char str2[] = "hello world.";// str1数组 和 str2数组 是两个相互独立的空间// 所以两者指向的 首元素地址 是不同的if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("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");elseprintf("str3 and str4 are not same\n");return 0;}

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

2.指针数组:

(1). 含义:

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

(2). 实例:

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

对应代码:

//使用指针数组模拟二维数组:#include 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结合,说明p是一个指针变量

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

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

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

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

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

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

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

实例:

对应代码:

//数组名的理解://数组名表示数组首元素地址,但有两个例外#include 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 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 . 函数指针的 调用: