---------------------------------------------------------------------------------------------------------------------------------
❤C语言中数组的名字代表啥?
❤数组怎么传参?
❤数组指针是啥?
---------------------------------------------------------------------------------------------------------------------------------
目录
1.数组名
int a[4]={1,2,3 };
int b[2][2]={11,22,33,44 };
在定义数组的时候,一般都如上边所述,用的时候a[1]=...,也就用了,但是很少会考虑a代表的是什么?在此记下,以防未来忘记。
你或许听到过如下解释:
🍬 a可以代表一个指向数组首元素的指针
这种说话算是对的,因为当你输出a的值的时候确实输出的是数组首元素的地址。
为啥说是算是,下面解释过后就清楚:
☀假设定义的两个数组在内存中的分配如下:
数组名的值一般为数组元素首地址(注意我说的是数值名的值)
☀现在我来介绍一种窗口滑动来阐述结论,该结论只是更好的理解*(a+1)+1,*a+1这种问题:
我们认为在数据创建的时候除了给其分配一串连续的内存空间外,还会产生一个窗口如下图,a正是代表这个窗口,而不是等于首元素的地址(只是数值相等)。一维数组会产生一层窗口,二维数组会产生两层窗口,n维...。规定:
🍬“数组名+1”是在数组名的第一层窗口(a)内进行滑动,滑动距离为该层内的单元数。eg:a+1即代表0x00000005。
“*(数组名+1)”是要在数组名的内一层窗口进行滑动,在一维数组当中已经是最小的单元了再进入不了了故进入地址中代表的值。eg:*(a+1)即代表a[1]。
🍬“&数组名+1”代表在数组名的还要外一层进行滑动,就会出现如下图所示:eg:&a+1即代表0x00000011。
二维数组的情况也是运用上面的结论,二维数组由于本身会产生两层窗口(b)(外面的不算其产生的),情况稍微复杂一点。
下面直接举例子:
🍬b+1代表b滑动了窗口,代表了0x00000019
🍬*(b+1)中的*可以理解为,向内进入一层窗口。*(b+1)代表着由0x00000019、0x0000001D组成的窗口,由于它代表的还是窗口,所以他的值还是地址值,为窗口中的首元素的地址值即0x00000019
🍬因为*(b+1)代表的还是窗口,在他的窗口内还可以进行滑动,*(b+1)+1即代表其窗口内的第二个值的地址(第一个值的地址由*(b+1)+0表示)。
🍬有点套娃了...那么怎么表示地址里面的值呢?当*(b+1)+1时,其值为0x0000001D,它可以看作是一个单元窗口,要想看他的值只需用*进入即可。eg:*(*(b+1)+1),它的值时44。
🍬还要再说一下&b+1,向外出一层窗口。(这个就类似&a+1),其表示的是0x00000021。
下面在进行一些数组名字的操作的时候是不是就容易理解多了。可以去实践一下。
//一维数组的名字的操作
printf("%d\n",a+1); //0x00000005 只是理想的内存分配,实际不可能从0x00000000开始
printf("%d\n",&a+1);//0x00000011
//2维数组的名字的操作
printf("%d\n",b+1);
printf("%d\n",&b+1);
2.数组当作参数传递的时候
#include <stdio.h>
#include <stdlib.h>
void test_1(int b[3][3])
{
b[0][0] = 11;
b[1][1] = 22;
b[2][2] = 33;
return 0;
}
void printf_a(int c[3][3],int imax,int jmax)
{
int i,j;
for (i=0;i<imax;i++)
{
for (j=0;j<jmax;j++)
{
printf("%d\n",c[i][j]);
}
}
return 0;
}
int main()
{
int a[3][3] = { 1,2,3,4,5,6,7,8,9 };
后验证编译器报错不通过test_1(a[3][3]);//函数test_1里面形参改变不不不会影响a[][]的值
test_1(a);//函数test_1里面形参改变会影响a[][]的值
后验证编译器报错不通过printf_a(a[3][3],3,3);//这样传递会出现错误,出现数组内元素错误
printf_a(a,3,3);//这样传递正确,不会出现数组内元素错误。
return 0;
}
3.指针de数组
指针数组是数组,数组里面存放的是地址;
代码如下:
#include<stdio.h>
int main()
{
int *a[10];
int b,c,d,i;
b=11;
c=22;
d=33;
a[0]=&b;
a[1]=&c;
a[2]=&d;
for(i=0;i<3;i++)
{
printf("a=%d ",a);
printf("a+%d=%d ",i,a+i);
printf("*(a+%d)=%d ",i,*(a+i));
printf("*a+%d=%d ",i,*a+i);
printf("a[%d]=%d ",i,a[i]);
printf("a[0]+%d=%d ",i,a[0]+i);
printf("*a[%d]=%d\n",i,*a[i]);
}
return 0;
}
运行结果:
可以看到a[0]、a[1]和a[2]都可以当作一个指针看待。
其中比较特殊的一点是*a其实是代表的是地址,而地址加1之后,地址值并不是加1而是加4。
4.数组de指针
数组指针是指针:
int a[10]={11,22,33,4,5,6};
int (*p)[10]=&a;//代表一个指向数组的指针。
指向一个数组。
🍬时刻谨记:地址复制给指针。
🍬int (*p)[10];运用上面的结论代表生成两层窗口,第一层窗口尺度为10,(int (*p)[10];)
第二层窗口为未知个*第一层窗口尺度。其实大部分数组也是这样的。
🍬数组指针的作用:可以通过指针调用数组...好像只知道这些
举个例子:
#include<stdio.h>
int main()
{
int a[10]={11,22,33,44,55,66};//这里是10
int i;
int (*p)[6]=&a;//在这里故意生成了一个6,看看能调用到哪里
for(i=0;i<10;i++)
{
printf("a[%d]=%d ",i,a[i]);
printf("&a[%d]=%d ",i,&a[i]);
printf("p[%d]=%d ",i,p[i]);
printf("*p+%d=%d ",i,*p+i);
printf("*(*p+%d)=%d\n",i,*(*p+i));
}
return 0;
}
运行结果:
可以的看到调用的格式是*(*p+1)=22。