⭐博主: 清炒莲藕拌饭
⭐博客:(10条消息) 清炒莲藕拌饭的博客_CSDN博客-C语言领域博主
⭐专栏:(10条消息) C语言_清炒莲藕拌饭的博客-CSDN博客
⭐专栏介绍:包含从C语言初阶到进阶各各知识点进行讲解,用C语言写的各种小程序,大体围绕C基础为主的专栏;
本篇博客介绍重点✒️
1. 字符指针
2. 数组指针
3. 指针数组
4. 数组传参和指针传参
5. 函数指针
1.字符指针樂 前言回顾:
1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。
3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。 4. 指针的运算。
前面我们应该也见过 char* 字符指针,一般出现下面使用情况:
int main()
{
char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}
int main()
{
const char* pstr = "hello";//这里是把一个字符串放到pstr指针变量里了吗?
printf("%sn", pstr);
return 0;
}
樂 打印结果就是hello,那是不是pstr里面就存放的字符串hello呢?千万不要这样认为,指针变量都是存放地址的,pstr应该说是存放字符串首元素的地址,printf打印就会按照这个地址打印下去,遇到 就会停止打印;
上面的代码看明白了我们来看下面这段代码:
#includeint main() { char str1[] = "hello bit."; char str2[] = "hello bit."; const char *str3 = "hello bit."; const char *str4 = "hello bit."; if(str1 ==str2) printf("str1 and str2 are samen"); else printf("str1 and str2 are not samen"); if(str3 ==str4) printf("str3 and str4 are samen"); else printf("str3 and str4 are not samen"); return 0; } 问打印结果是什么?
题解:
首先了解str1==str2 和 str3==str4是什么意思,这个表达式其实表示在比较它们的地址是否相同,那么str1和str2它们是两个不相同的数组,地址怎么可能一样呢?而str3和str4它们都是字符常量,不需要在内存中开辟新的空间,它们的首地址都是指向字符‘h’的,所以地址肯定也一样;
2.指针数组指针数组就是一个存放指针类型的数组,它里面的元素都是指针类型;
int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5]; //二级字符指针的数组
优先级理解:arr1先和[ 10 ]结合,说明这就是一个数组,数组的类型是它前面int *,说明这是一个指针数组,用来存放指针的;
⭐3.数组指针 3.1 数组指针的定义数组指针是什么?
它是指针,指向数组的指针,我们前面已经知道有int *pa 整型指针 , float *pb 浮点型指针,它们都是指向某个类型的指针,那么数组指针也一样,它指向的类型是一个数组;
int * arr1[10] = { 0 };
int (* arr2)[10] = { 0 }; //arr1和arr2分别是什么?
arr1前面我们已经介绍过了,它是指针数组;
arr2注意看它的(*arr2),这说明无论如何arr2已经和*结合了,这就表明arr2就是指针了而不是数组名了,因为它没有机会和[10]去结合了,而指向的类型就是int [10],所以我们叫它数组指针;
3.2 &数组名VS数组名注意:因为[ ]的优先级比*高,arr2会先和[10]结合,所以你如果想要的是一个数组指针就必须加上()让*和arr2先结合,这样才能保证arr2是一个数组指针;
int arr[10] = { 0 };
&arr和arr有什么不一样的吗?好像是一模一样的,arr是数组首元素地址&arr同样也是首元素地址,居然一样何必这么麻烦还要用&呢?
我的答案是NO! 编程讲究严谨,那么它的语法更是如此,存放的内容一样不代表它们意义就相等了,空口无凭下面我就带大家来研究&arr和arr的区别;
我们打印它们的地址确实一样
#includeint main() { int arr[10] = {0}; printf("%pn", arr); printf("%pn", &arr); return 0; } 运行结果:
但是我们来看下面这段代码:
#includeint main() { int arr[10] = { 0 }; printf("arr = %pn", arr); printf("arr+1 = %pn", arr + 1); printf("&arr= %pn", &arr); printf("&arr+1= %pn", &arr + 1); return 0; }
运行结果:
这说明什么?&arr和arr虽然值一样,但是它们的意义肯定不一样,所以有些事我们不要被表象迷惑,事情有疑点那我们就刨根问底然后将它斩于马下;事实上&arr是代表数组所有元素的地址,但是总得有一个地址来表达它们,但是空间又有限不可能将所有的元素地址表达出来,所以还是使用了数组首元素来来代表它们,但是它的意义却不一样了;
3.3数组指针的使用樂思考:
&arr大家可以仔细想一想它是什么?它是不是一个数组指针啊,确实是的,&arr所指向的就是arr整个数组,在本案例中它的类型是int (*)[10];
数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40.
既然有数组指针这个东西那我们应该怎么使用呢?
栗子1(不常用):
#includeint main() { int arr[10] = {1,2,3,4,5,6,7,8,9,0}; int (*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p //但是我们一般很少这样写代码 return 0; }
栗子2(常用):
#includevoid print_arr1(int arr[3][5], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { printf("%d ", arr[i][j]); } printf("n"); } } void print_arr2(int(*arr)[5], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { printf("%d ", arr[i][j]); } printf("n"); } } int main() { int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 }; print_arr1(arr, 3, 5); //数组名arr,表示首元素的地址 //但是二维数组的首元素是二维数组的第一行 //所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址 //可以数组指针来接收 print_arr2(arr, 3, 5); return 0; }
学了指针数组和数组指针我们来一起回顾并看看下面代码的意思:
4.数组参数,指针参数int arr[5]; //整型数组
int *parr1[10]; //指针数组
int (*parr2)[10]; //数组指针
int (*parr3[10])[5]; //存放数组指针的数组
在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?
4.1一维数组传参#include4.2 二维数组传参void test(int arr[])//ok {} void test(int arr[10])//ok {} void test(int *arr)//ok {} void test2(int *arr[20])//ok {} void test2(int **arr)//ok {} int main() { int arr[10] = {0}; int *arr2[20] = {0}; test(arr); test2(arr2); return 0; }
void test(int arr[3][5])//ok?
{}
void test(int arr[][])//ok?
{}
void test(int arr[][5])//ok?
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int *arr)//ok?
{}
void test(int* arr[5])//ok?
{}
void test(int (*arr)[5])//ok?
{}
void test(int **arr)//ok?
{}
int main()
{
int arr[3][5] = {0};
test(arr);
}
4.3 一级指针传参
#includevoid print(int *p, int sz) { int i = 0; for(i=0; i 樂当一个函数的参数部分为一级指针的时候,函数能接收什么参数?
4.4 二级指针传参#includevoid test(int** ptr) { printf("num = %dn", **ptr); } int main() { int n = 10; int*p = &n; int **pp = &p; test(pp); test(&p); return 0; } 樂当函数的参数为二级指针的时候,可以接收什么参数?



