个人主页深邃-❄️专栏传送门《C语言》《数据结构》Gitee仓库《C语言》《数据结构》目录数组名的理解数组名两个例外使用指针访问数组(数组下标的本质)一维数组传参的本质二级指针指针数组指针数组指针数组模拟二维数组数组名的理解数组名先由一组代码来理解intmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};int*parr;printf(%d\n,*p);//1return0;}结论我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样数组名就是数组⾸元素 ( 第⼀个元素 ) 的地址。 \color{blue}{我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样数组名就是数组⾸元素(第⼀个元素)的地址。}我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样数组名就是数组⾸元素(第⼀个元素)的地址。.两个例外数组名就是数组⾸元素 ( 第⼀个元素 ) 的地址是对的但是有两个例外 \color{blue}{ 数组名就是数组⾸元素(第⼀个元素)的地址是对的但是有两个例外}数组名就是数组⾸元素(第⼀个元素)的地址是对的但是有两个例外sizeof(数组名)sizeof中单独放数组名这⾥的数组名表示整个数组计算的是整个数组的大小单位是字节数组名这⾥的数组名表示整个数组取出的是整个数组的地址整个数组的地和数组首元素的地址是有区别的 除此之外任何地方使用数组名数组名都表示首元素的地址intmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};printf(%zd\n,sizeof(arr));//40?//如果说arr是数组首元素的地址的话那这里不是计算一个地址的大小是4吗return0;}1. \color{green}{ 1.}1..显然计算的是数组的大小2. \color{green}{ 2.}2.//%p - 专门用来打印地址的是16进制的形式前面的0不会省略intmain(){intarr[]{1,2,3,4,5,6,7,8,9,10};//printf(%zd\n, sizeof(arr));//10*4 40printf(arr %p\n,arr);//首元素的地址printf(arr1 %p\n,arr1);//首元素的地址printf(arr[0] %p\n,arr[0]);//首元素的地址printf(arr[0]1 %p\n,arr[0]1);//首元素的地址printf(arr %p\n,arr);//数组的地址printf(arr1 %p\n,arr1);//数组的地址return0;}这⾥我们发现arr[0]和arr[0]1相差4个字节arr和arr1 相差4个字节是因arr[0] 和 arr 都是⾸元素的地址1就是跳过⼀个元素。但是arr 和 arr1相差40个字节这就是因为arr是数组的地址1 操作是跳过整个数组的。使用指针访问数组(数组下标的本质)看下列三组代码intmain(){intarr[10]{0};//给数组中存放1 2 3 4 5 6 7 8 9 10intszsizeof(arr)/sizeof(arr[0]);inti0;int*parr;for(i0;isz;i){scanf(%d,pi);}//打印出数组的所有内容for(i0;isz;i){printf(%d ,*(pi));}return0;}intmain(){intarr[10]{0};//给数组中存放1 2 3 4 5 6 7 8 9 10intszsizeof(arr)/sizeof(arr[0]);inti0;int*parr;for(i0;isz;i){scanf(%d,arr[i]);}//打印出数组的所有内容for(i0;isz;i){printf(%d ,arr[i]);}return0;}intmain(){intarr[10]{0};//给数组中存放1 2 3 4 5 6 7 8 9 10intszsizeof(arr)/sizeof(arr[0]);inti0;int*parr;for(i0;isz;i){scanf(%d,arri);}//打印出数组的所有内容for(i0;isz;i){printf(%d ,*(arri));}return0;}这三组代码都是遍历数组打印数组请看这一个代码intmain(){intarr[10]{0};//给数组中存放1 2 3 4 5 6 7 8 9 10intszsizeof(arr)/sizeof(arr[0]);inti0;int*parr;for(i0;isz;i){scanf(%d,arri);}//打印出数组的所有内容for(i0;isz;i){printf(%d ,i[arr]);}return0;}写反了怎么还能打印呢本质arr[i] 应该等价于 *(arri)数组元素的访问在编译器处理的时候也是转换成元素的地址偏移量求出元素的地址然后解引⽤来访问的。arr[i] *(arr i) *(i arr) i[arr]一维数组传参的本质数组名是数组⾸元素的地址那么在数组传参的时候传递的是数组名也就是说本质上数组传参传递的是数组首元素的地址。所以函数形参的部分理论上应该使⽤指针变量来接收⾸元素的地址。那么在函数内部我们写sizeof(arr) 计算的是⼀个地址的大小单位字节⽽不是数组的大小单位字节。正是因为函数的参数部分是本质是指针所以在函数内部是没办法求的数组元素个数的。voidtest(intarr[10])//形参写成一维数组{intsz2sizeof(arr)/sizeof(arr[0]);printf(2: %d\n,sz2);}voidtest(int*arr,intsz)//形参写成一维数组{intsz2sizeof(arr)/sizeof(arr[0]);//在函数内求参数部分的数组的元素个数是错误的printf(2: %d\n,sz2);//8 / 4 2inti0;for(i0;isz;i){printf(%d ,arr[i]);//arr[i] *(arri)}}intmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};intsz1sizeof(arr)/sizeof(arr[0]);printf(1: %d\n,sz1);test(arr,sz1);//传的是一维数组return0;}在函数内求参数部分的数组的元素个数是错误的这就是为什么传数组的时候也要传元素个数总结⼀维数组传参形参的部分可以写成数组的形式也可以写成指针的形式。二级指针指针变量也是变量是变量就有地址那指针变量的地址存放在哪⾥这就是二级指针intmain(){inta10;int*paa;int**ppapa;a200;printf(%d\n,**ppa);//200return0;}二级指针变量是用来存放一级指针变量的地址的指针数组指针数组类比⼀下整型数组是存放整型的数组字符数组是存放字符的数组。那指针数组呢是存放指针的数组此时发现存放指针类型的一维数组与二维数组好像那就用一维数组模拟一下二维数组指针数组模拟二维数组intmain(){intarr1[]{1,2,3,4,5};intarr2[]{2,3,4,5,6};intarr3[]{3,4,5,6,7};int*arr[]{arr1,arr2,arr3};//arr是指针数组inti0;for(i0;i3;i){intj0;for(j0;j5;j){printf(%d ,arr[i][j]);}printf(\n);}return0;}根据刚刚所学我们还可以随心所欲的打印intmain(){intarr1[]{1,2,3,4,5};intarr2[]{2,3,4,5,6};intarr3[]{3,4,5,6,7};int*arr[]{arr1,arr2,arr3};//arr是指针数组inti0;for(i0;i3;i){intj0;for(j0;j5;j){//printf(%d , *(*(arr i) j));//printf(%d , *(arr[i] j));printf(%d ,(*(arri))[j]);}printf(\n);}return0;}但是要注意一处如下导致错误的原因是数组下标的优先级比解引用优先级高再用图清晰的解释一下parr[i]是访问parr数组的元素parr[i]找到的数组元素指向了整型⼀维数组parr[i][j]就是整型一维数 组中的元素。上述的代码模拟出⼆维数组的效果实际上并非完全是⼆维数组因为每一行并非是连续的感谢大佬们三连你的鼓励就是对我创作的激励
C语言指针(2)
个人主页深邃-❄️专栏传送门《C语言》《数据结构》Gitee仓库《C语言》《数据结构》目录数组名的理解数组名两个例外使用指针访问数组(数组下标的本质)一维数组传参的本质二级指针指针数组指针数组指针数组模拟二维数组数组名的理解数组名先由一组代码来理解intmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};int*parr;printf(%d\n,*p);//1return0;}结论我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样数组名就是数组⾸元素 ( 第⼀个元素 ) 的地址。 \color{blue}{我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样数组名就是数组⾸元素(第⼀个元素)的地址。}我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样数组名就是数组⾸元素(第⼀个元素)的地址。.两个例外数组名就是数组⾸元素 ( 第⼀个元素 ) 的地址是对的但是有两个例外 \color{blue}{ 数组名就是数组⾸元素(第⼀个元素)的地址是对的但是有两个例外}数组名就是数组⾸元素(第⼀个元素)的地址是对的但是有两个例外sizeof(数组名)sizeof中单独放数组名这⾥的数组名表示整个数组计算的是整个数组的大小单位是字节数组名这⾥的数组名表示整个数组取出的是整个数组的地址整个数组的地和数组首元素的地址是有区别的 除此之外任何地方使用数组名数组名都表示首元素的地址intmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};printf(%zd\n,sizeof(arr));//40?//如果说arr是数组首元素的地址的话那这里不是计算一个地址的大小是4吗return0;}1. \color{green}{ 1.}1..显然计算的是数组的大小2. \color{green}{ 2.}2.//%p - 专门用来打印地址的是16进制的形式前面的0不会省略intmain(){intarr[]{1,2,3,4,5,6,7,8,9,10};//printf(%zd\n, sizeof(arr));//10*4 40printf(arr %p\n,arr);//首元素的地址printf(arr1 %p\n,arr1);//首元素的地址printf(arr[0] %p\n,arr[0]);//首元素的地址printf(arr[0]1 %p\n,arr[0]1);//首元素的地址printf(arr %p\n,arr);//数组的地址printf(arr1 %p\n,arr1);//数组的地址return0;}这⾥我们发现arr[0]和arr[0]1相差4个字节arr和arr1 相差4个字节是因arr[0] 和 arr 都是⾸元素的地址1就是跳过⼀个元素。但是arr 和 arr1相差40个字节这就是因为arr是数组的地址1 操作是跳过整个数组的。使用指针访问数组(数组下标的本质)看下列三组代码intmain(){intarr[10]{0};//给数组中存放1 2 3 4 5 6 7 8 9 10intszsizeof(arr)/sizeof(arr[0]);inti0;int*parr;for(i0;isz;i){scanf(%d,pi);}//打印出数组的所有内容for(i0;isz;i){printf(%d ,*(pi));}return0;}intmain(){intarr[10]{0};//给数组中存放1 2 3 4 5 6 7 8 9 10intszsizeof(arr)/sizeof(arr[0]);inti0;int*parr;for(i0;isz;i){scanf(%d,arr[i]);}//打印出数组的所有内容for(i0;isz;i){printf(%d ,arr[i]);}return0;}intmain(){intarr[10]{0};//给数组中存放1 2 3 4 5 6 7 8 9 10intszsizeof(arr)/sizeof(arr[0]);inti0;int*parr;for(i0;isz;i){scanf(%d,arri);}//打印出数组的所有内容for(i0;isz;i){printf(%d ,*(arri));}return0;}这三组代码都是遍历数组打印数组请看这一个代码intmain(){intarr[10]{0};//给数组中存放1 2 3 4 5 6 7 8 9 10intszsizeof(arr)/sizeof(arr[0]);inti0;int*parr;for(i0;isz;i){scanf(%d,arri);}//打印出数组的所有内容for(i0;isz;i){printf(%d ,i[arr]);}return0;}写反了怎么还能打印呢本质arr[i] 应该等价于 *(arri)数组元素的访问在编译器处理的时候也是转换成元素的地址偏移量求出元素的地址然后解引⽤来访问的。arr[i] *(arr i) *(i arr) i[arr]一维数组传参的本质数组名是数组⾸元素的地址那么在数组传参的时候传递的是数组名也就是说本质上数组传参传递的是数组首元素的地址。所以函数形参的部分理论上应该使⽤指针变量来接收⾸元素的地址。那么在函数内部我们写sizeof(arr) 计算的是⼀个地址的大小单位字节⽽不是数组的大小单位字节。正是因为函数的参数部分是本质是指针所以在函数内部是没办法求的数组元素个数的。voidtest(intarr[10])//形参写成一维数组{intsz2sizeof(arr)/sizeof(arr[0]);printf(2: %d\n,sz2);}voidtest(int*arr,intsz)//形参写成一维数组{intsz2sizeof(arr)/sizeof(arr[0]);//在函数内求参数部分的数组的元素个数是错误的printf(2: %d\n,sz2);//8 / 4 2inti0;for(i0;isz;i){printf(%d ,arr[i]);//arr[i] *(arri)}}intmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};intsz1sizeof(arr)/sizeof(arr[0]);printf(1: %d\n,sz1);test(arr,sz1);//传的是一维数组return0;}在函数内求参数部分的数组的元素个数是错误的这就是为什么传数组的时候也要传元素个数总结⼀维数组传参形参的部分可以写成数组的形式也可以写成指针的形式。二级指针指针变量也是变量是变量就有地址那指针变量的地址存放在哪⾥这就是二级指针intmain(){inta10;int*paa;int**ppapa;a200;printf(%d\n,**ppa);//200return0;}二级指针变量是用来存放一级指针变量的地址的指针数组指针数组类比⼀下整型数组是存放整型的数组字符数组是存放字符的数组。那指针数组呢是存放指针的数组此时发现存放指针类型的一维数组与二维数组好像那就用一维数组模拟一下二维数组指针数组模拟二维数组intmain(){intarr1[]{1,2,3,4,5};intarr2[]{2,3,4,5,6};intarr3[]{3,4,5,6,7};int*arr[]{arr1,arr2,arr3};//arr是指针数组inti0;for(i0;i3;i){intj0;for(j0;j5;j){printf(%d ,arr[i][j]);}printf(\n);}return0;}根据刚刚所学我们还可以随心所欲的打印intmain(){intarr1[]{1,2,3,4,5};intarr2[]{2,3,4,5,6};intarr3[]{3,4,5,6,7};int*arr[]{arr1,arr2,arr3};//arr是指针数组inti0;for(i0;i3;i){intj0;for(j0;j5;j){//printf(%d , *(*(arr i) j));//printf(%d , *(arr[i] j));printf(%d ,(*(arri))[j]);}printf(\n);}return0;}但是要注意一处如下导致错误的原因是数组下标的优先级比解引用优先级高再用图清晰的解释一下parr[i]是访问parr数组的元素parr[i]找到的数组元素指向了整型⼀维数组parr[i][j]就是整型一维数 组中的元素。上述的代码模拟出⼆维数组的效果实际上并非完全是⼆维数组因为每一行并非是连续的感谢大佬们三连你的鼓励就是对我创作的激励