一、数组指针 初学C语言的朋友对数组指针这指针数组感到迷惑,分不清,包括我自己,其实是对概念的不清晰以及对数组和指针这两个概念理解的不够深入,下面谈谈我的理解。 int的数组的指针类型A int a[5]; A q = &a;//用类型定义变量 3.直接定义数组指针变量 int a[5] = {1,2,3,4,5}; int (*q)[5] = &a;//q 是数组指针变量 二、指针数组 指针数组,是一个数组,而不是指针。 ,这个指针指向.rodata对应的常量字符串 指针数组的应用 完整的main函数原型,int main(int arc,char* argv[],char* envp[]) 其中,两个数组分别保存命令行参数和环境变量 为了提高程序执行的效率,C语言不做数组下标的安全性检查。如果进行了检查当数组数据量非常大时候会显著减低程序的效率,在安全性和高效率之间,权衡利弊之下。
int a1,a2,a3; p[0]=&a1; p[1]=&a2; p[2]=&a3; 在理解: 数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的一维数组 如要将二维数组赋给一指针,应这样赋值: int a[3][4]; int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。 如要将二维数组赋给一指针数组: int *p[3]; int a[3][4]; p++; //该语句表示p数组指向下一个数组元素。 注:此数组每一个元素都是一个指针 for(i=0;i<3;i++) p[i]=a[i] 这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2] 所以要分别赋值 还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
那arr和&arr有啥区别呢? 这⾥我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1 相差4个字节,是因为&arr[0] 和 arr 都是⾸元素的地址,+1就是跳过⼀个元素。 但是&arr 和 &arr+1相差40个字节,这就是因为&arr是数组的地址,+1 操作是跳过整个数组的。 printf ( "sz2 = %d\n" , sz2); } int main () { int arr[ 10 ] = { 1 , 2 , 3 指针数组的每个元素都是⽤来存放地址(指针)的。 七 指针数组模拟⼆维数组 1限制:每个数组元素个数一样,不一样最好别用很麻烦。
数组的地址类型和普通元素的地址是不一样,arr和&arr[0]的类型都是int*,一个整型指针。 因为加法支持交换律,就有下面这种图 类似于1+2=2+1,同理i[arr]在编译器执行时也会转换为第3个,这里第一种写法有提过数组名和下标,第四种也提过数组名和下标,[ ]只是个操作符而已。 = { &a,&b,&c }; //arr就是指针数组 return 0; } 这里存三个变量的地址,就要创建3个指针变量,有点麻烦了,就可以用指针数组 数组的每个元素是int*,数组大小也会根据初始化内容自行设置 七、指针数组模仿二维数组 使用指针数组,模拟一个二维数组 int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = 总结 以上就是指针篇(3)的全部内容了,明天开始主播要复习期末了,指针后面的内容就要等考试结束找时间写了。
一、指针数组 解释:一个数组,若其元素均为指针类型数据,称为指针数组 一般形式 类型名 *数组名[数组长度] 二、指向指针数据的指针 解释:指向指针数据的指针声明的是指针,只是这指针指向另一个指针 例子 三、指针数组作main函数的形参 int mian(int argc,char *argv[]) 其中argc和argv就是mian函数的参数,他们是程序的“命令行参数” 命令行的一般形式 命令名 参数 1 参数2 ......参数n 注意:命令名和各参数之间用空格分隔开
01 什么是指针数组 1、一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。 2、一般形式 类型名 *数组名[数组长度]; 类型中应包括符合*,如int *表示是指向整数数据的指针类型。 3、例子 int *p[4]; 4、由于[]比*优先级高,因此p先和[4]结合,形成p[4]形式,这显然是数组形式,表示p数组有4个元素。 然后再和p前面的*结合,*表示此数组是指针类型的,每个数组元素都可以指向一个整型变量。 02 指向指针数据的指针 1、在了解了指针数组的基础上,需要了解指向指针数据的指针变量,简称指向指针的指针。 3、命令行的一般形式 命令名 参数1 参数2……参数n 有时候,正是那些意想不到之人,成就了无人能成之事。 ——图灵 ? 文字/闫小林 图片/源于网络 - END -
,而前面的 int 是指针变量p 要指向的变量的类型; 例如: #include<stdio.h> int main() { int *p,i;//定义整形指针变量p,和普通变量i; p= ,所以*自然就是指针变量的标志了,在定义的同时,指向一个变量,其实就是把定义和取地址,合并了起来,这两个代码是等同的; 那接下来我们开始了解通过指针访问变量地址,话不多说上代码: 如图:我将普通变量的地址放在了指针变量 3.打印的第一行和打印的第3行的地址是相同的,说明数组名就是数组首元素的地址,而对数组取地址的这个地址也同样是数组首元素的地址: 结论:二者都是数组首元素的地址,不同的是,步长大小不同; 我们再回到数组指针上 指针数组 含义 指针数组,主体是数组,不同的是里面存的是指针,是地址; 指针数组打印二维数组 值得注意的是指针数组的[]前面的*p是没有括号的,我们可以这样看,他是一个数组,数组名是p,数组元素个数是3 ,(3个地址),p的前面加上一个*,就是指针,那就是指针数组啦, 总结:1.指针数组的形如*p[n]的数组,而数组指针是指针指向的是数组,形如(*p)[n],里面存的不是数组首元素的地址,而是整个数组的地址
组指针:存放的是数组的地址,能够指向数组的指针变量 二、指针数组和数组指针的区别 数组指针和指针数组的写法 int*parr[10]//指针数组 解释:数组名先和[]结合,说明这是一个数组,数组中有 int(*p2)[10]//数组指针 解释:p2先和(*)结合说明p2是一个指针变量,然后指针指向的是一个大小为10个整形的数组,,所以p2是一个指针,叫做数组指针。 同时我们观察发现,函数名和取出来的地址是一样的 函数指针变量的使用 如果我们要将函数的地址存放起来,就得创建函数指针变量咯,函数指针变量的写法其实和数组指针非常类似。 其实也是可以的,比如,将 int* 重命名为 ptr_t ,这样写: typedef int* ptr_t; 但是对于数组指针和函数指针稍微有点区别: 比如我们有数组指针类型 int(*)[5 定义: int(*parr[3])(); 解释:parr先和[]结合表明这是一个数组,数组的内容是什么,是int(*)()类型的函数指针 函数指针数组的实际应用:转移表 计算器的一般实现路径代码
2-2 误区: 2-3 代码一和代码二的异同: 2-4 关于字符常量区: 2-5 一道为了区分栈区和字符常量区&&字符数组和字符指针的面试题: 3.指针数组 3-1 指针数组长什么样捏? 数组指针 4-1 区分取地址数组名和数组名(老生常谈了) 4-2 辨析数组指针和指针数组 4-3 学会了? ,弃之可惜 //实际上作用大着捏,我们指针数组的意义和普通数组的意义类似, //都是对方便对相同类型元素(在这里的类型元素是指针)统一处理:比如修改和打印 3-2 初级使用(或者说给你看一下基本使用): 【指针数组模拟打印二维数组】 这和arr[3][5]的区别在于arr[3][5]在内存中中每一个元素的地址都是连续的,而指针数组模拟的二维数组这种方式的地址不是连续的。 5 测试题和规律总结 测验1: 如果int(*arr[3])[5]; 问题:怎么理解这个代码? 答案:数组指针数组 测验2:那么指针数组指针?
文章目录 总结 一、使用 数组指针类型 定义数组指针 二、完整代码示例 总结 // 首先 , 定义 数组指针类型 别名 typedef int(*ArrayPointer)[3]; typedef 定义一个数组指针类型 , typedef int(*ArrayPointer)[3]; 然后 , 定义一个普通数组 , 之后的 数组指针 指向该数组 , int array2 [3] = {0}; 最后 , 声明一个 数组指针类型 变量 , 将 array2 变量地址赋值给该 数组指针类型 变量 , 指针指向的数据类型为 int[3] 数组类型的变量 array2 ; 别名 typedef int(*ArrayPointer)[3]; // 然后 , 定义一个普通数组 , 之后的 数组指针 指向该数组 int array2[3] = {0} ; // 最后 , 声明一个 数组指针类型 变量 // 将 array2 变量地址赋值给该 数组指针类型 变量 // 指针指向的数据类型为 int[3] 数组类型的变量 array2
指针数组 :就是指针的数组,数组的元素是指针; 数组指针:就是指向数组的指针。 简单举例说明: int *p1[10]; 声明了一个数组,数组的元素是int型的指针。 int (*p2)[10]; 声明了一个指针, 指向了一个有十个int元素的数组。 这两种写法主要是因为运算符的优先级, 因为[]的优先级比*高。 第一种写法:p先和[]结合,所以是一个数组,后与*结合,是指针数组。 第二种写法:()的优先级比[]高,*号和p2构成一个指针的定义,指针变量名为p,int 修饰的是数组的内容,即数组的每个元素。 数组在这里并没有名字,是个匿名数组, 那现在我们清楚p 是一个指针,它指向一个包含10 个int 类型数据的数组,即数组指针 ? int a[3]={1,2,3}; int (*p)[3]=&a;//指向3个int型数组元素的数组指针 int* p2[3]; //存贮3个int型变量地址 for(int i=0;i<3
下面的摘取的例子特别具有说明性: 以后再也不敢说指针和数组一样啦!
01什么是指针数组 1、一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。 2、一般形式 类型名 *数组名[数组长度]; 类型中应包括符合*,如int *表示是指向整数数据的指针类型。 3、例子 int *p[4]; 4、由于[]比*优先级高,因此p先和[4]结合,形成p[4]形式,这显然是数组形式,表示p数组有4个元素。 然后再和p前面的*结合,*表示此数组是指针类型的,每个数组元素都可以指向一个整型变量。 02指向指针数据的指针 1、在了解了指针数组的基础上,需要了解指向指针数据的指针变量,简称指向指针的指针。 3、命令行的一般形式 命令名 参数1 参数2……参数n C语言 | 递归求年龄 更多案例可以go公众号:C语言入门到精通
一、数组笔试题解析 知识点: 只要是地址就是4/8个字节 数组名 数组名是数组首元素的地址 但是有2个例外: 1. sizeof(数组名) - 数组名表示整个数组,计算的是整个数组的大小 &数组名 - 数组名也表示整个数组,取出的是整个数组的地址 除了这个2个例外,你见到的所有的数组名都表示首元素的地址 sizeof sizeof 是计算对象或者类型创建的对象所占内存空间的大小 二维数组题目 int a[3][4] = {0}; printf("%d\n",sizeof(a)); printf("%d\n",sizeof(a[0][0])); printf("%d\n",sizeof )); 题目解析及运行结果: ---- 二、指针笔试题 笔试题1: int main() { int a[5] = { 1, 2, 3, 4, 5 }; int *ptr = (int 结语: 这里我们关于指针笔试题的内容就介绍完了,如果小伙伴还有不理解的内容,可以参考之前关于指针进阶的博文。
函数指针和其类似,只不过其指向的不是一个变量,而是一个函数,仅此而已。话不多说,看个例子。 简单的5行代码就完成了一个简单的函数指针。我们一行行来看。 第一行。声明了一个函数指针。其和普通指针有啥区别。我放在一起让大家看一下。 所以说函数指针是个很好用的东西。 2. 函数指针数组 函数指针说完了。我们接下来来看看函数指针数组。 多了俩字。数组。前面四个字还一样。那是不是就是有一个数组,用它来盛放函数指针。 void (*funcPointerArray[3])(double x);//函数指针数组void (*funcPointer)(double x);//函数指针 两个放在一起对比,函数指针数组无非就像数组声明一样 好了,相信讲到这里,大家应该清楚的明白什么是函数指针和函数指针数组了。
多维数组 和 多维指针 1. 多维数组 和 多维指针 1. 分别申请 数组指针空间 和 数据空间 ; ( 1 ) 申请数组指针空间 : 申请三个 数组指针 空间, 只是三个普通的指针, 但是该指针类型是 int(*)[3], 即指向 int[3] 数组的指针 _2d 是一个完整的数组指针, 该指针中包含着 其指向的数组的 类型 和 大小 ( 3 ) 数组指针退化时, 退化的只是 array_2d 的 数组指针 数组 (最外层的一维数组) 大小, , 其指针变量名称写在中间的括号中 ; 3.数组指针混合函数指针 : 如果出现了 数组指针 指向一个函数, 这个指针可读性很差, 理解需要一定的功力 ; 复杂指针阅读技巧 ( 主要是 区分 函数指针 和
文章目录 总结 一、直接定义 数组指针 二、完整代码示例 总结 int (*p)[3] = NULL; 一、直接定义 数组指针 ---- 直接定义 数组指针 , 首先 , 定义一个普通数组 , 之后的 数组指针 指向该数组 , int array2[3] = {0}; 然后 , 直接定义数组类型变量 , int (*p)[3] = NULL; 最后 , 将 array2 变量地址赋值给该 数组指针类型 变量 , 指针指向的数据类型为 int[3] 数组类型的变量 array2 ; ArrayPointer p = NULL; p = &array2; 验证上述 定义的数组指针 ; } 使用 数组指针 , 打印数组元素内容 : // 使用 数组指针 访问数组中的值 for(i = 0; i < 3; i++) { printf(" , 之后的 数组指针 指向该数组 int array2[3] = {0}; // 然后 , 直接定义数组类型变量 int (*p)[3] = NULL; // 最后
空指针和野指针 野指针:定义了一个指针变量,如果没有进行初始化,系统就会有可能随机赋值一个地址给这个指针变量,也就是说,这个指向指向一个未知的区域。 图片 图片 PS: 区分指针数组int *a[3]和数组指针int (*a)[3],前者时存放指针的数组,后者是指向数组的指针。 如要将二维数组赋给一指针数组: int *p[3]; int a[3][4]; p++; //该语句表示p数组指向下一个数组元素。 指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。 还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。 ()”的优先级比“[]”高,“*”号和p2 构成一个指针的定义,指针变量名为p2,int 修饰的是数组的内容,即数组的每个元素。
PS: 区分指针数组int *a[3]和数组指针int (*a)[3],前者时存放指针的数组,后者是指向数组的指针。 指针数组和数组指针 int *b可以用来定义数组 int a = [1,2,3,4,5]; int *b = a; int (*b)[5]用来指向数组 int a = [1,2,3,4,5]; int 如要将二维数组赋给一指针数组: int *p[3]; int a[3][4]; p++; //该语句表示p数组指向下一个数组元素。 还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。 号和p2 构成一个指针的定义,指针变量名为p2,int 修饰的是数组的内容,即数组的每个元素。
形式辨析 int * p; 首先*表示这是一个指针,命名为p,然后指向的是int类型的指针,数组指针也一样 int(*p) [5]; 上面的形式就是数组指针,我们需要先用()把*和指针名括起来,然后剩下的就是指针指向的类型 数组指针一般和二维数组联动。 因为数组指针存放的是一整个数组的地址,而二维数组传参,二维数组的数组名就表示这个二维数组首行的地址(注意是首行的地址!) [3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 }; print(arr, 3, 5);//二维数组传参表示二维数组第一行的地址 return 0; } 二维数组的传参 形参接收分为数组接收和指针接收。 int,void(*)(int),函数应该还有函数的返回类型,此时把前面的signal和两个参数全部去掉,发现剩下void(*)(int),这就是函数的返回类型!