C语言作为很多大学理工科都会学习的语言,作为一种编程入门语言。
但是相对于其他高级编程语言来说相对是比较难,尤其是指针,不知道有多少莘莘学子都是因为它,从C语言入门到放弃。
想当年,笔者在大一学习C语言时也是被折磨的不轻,那个时候弄冒泡排序都不会。可能是那个时候逻辑思维不行吧,感觉工作后思维能力变强了,难道是被逼的,不知道你们有没有这种感觉。
不扯了!
进入主题,今天来探讨二维数组名到时是个啥?与数组地址、首行地址、首行首元素地址、指针到底有什么关系区别。
在C语言中地址就是指针,指针就是地址。我们的数组名也是地址,但是它到底是谁的地址呢?
有人说是数组地址,有人说是首元素地址,如果是二维数组 有人或许会说是首行地址。
没毛病,他们的值都是相等,他们都重叠在一起的!但是他们所代表的意义却大不一样。下面用代码来揭开他们的神秘面纱。
/*
测试 二维数组 数组名和整个数组地址、首行地址、首行首地址的区别和联系
*/
void arrPositonTest()
{
char a[4][30] = { "abcd","efjh","ijkl","mnop" };
//&a 代表的是数组首地址,+1 步长=4*30*1 = 120
printf("&a=%d,&a+1=%d\n", &a, &a + 1);
//a 也就是数组名 代表的是数组首行地址,+1 跳过一行 步长=1*30*1=30
printf("a=%d,a+1=%d\n",a,a+1);
//a 是首行地址 步长是整个一维数组,也是整个一维数组的首地址 。(*一维数组首地址) 就是首元素地址,不理解可看一维数组地址分析。
//*a 就是首行首元素地址,+1 跳过一个元素 步长 = 1*1
printf("*a=%d,*a+1=%d\n", *a, *a + 1);
//尽管 整个二维数组地址、首行地址、首行首元素地址他们的值是一样的,但是他们本质不一样,也就是+1代表的步长不一样!
printf("整个二维数组地址:%d,首行地址:%d,首行首元素地址:%d\n",&a,a,*a);
//我们知道*a代表二维数组首行首元素地址,那么**a 也就是首行首元素的内容了!
//*(*a+0):第一个元素内容,*(*a+1):第二个元素内容,*(*a+30):第二行第一个元素内容,*(*a+31):第二行第二个元素内容。
printf("**a:%c,*(*a+1):%c,*(*a+30):%c,*(*a+31):%c\n", *(*a + 0), *(*a + 1), *(*a + 30), *(*a + 31));
//当然我们取第二行元素的内容,同样可以使用第二行行地址来取。
//a+1代表第二行地址,*(a+1):第二行首元素地址,*(a+1)+1:第二行第二个元素地址,知道地址就可以用*取出内容。
//*(*(a+1)):第二行第一个元素内容,*(*(a+1)+1):第二行第二个元素内容。和上面取出来一样,从侧面也验证了二维数组在内存中还是线性存储的。
printf("*(*(a+1)):%c,*(*(a+1)+1):%c\n", *(*(a + 1)), *(*(a + 1) + 1));
//一维数组地址分析
char b[30] = { "wxyz" };
//&b 代表的是整个一维数组的首地址,+1 表示跳过整个一维数组 步长=1*30 = 30。
//相当于二维数组的数组名a 代表的数组首行地址 a+1 步长是整个一维数组的长度。
// *a 等价于 *(&b) b也就是数组首个元素的地址,所以*a +1是跳过一个元素。
printf("&b=%d,&b+1=%d\n", &b, &b + 1);
//b 也就是一维数组名 代表首元素地址,+1 跳过一个元素 步长=1*1=1
printf("b=%d,b+1=%d\n",b,b+1);
//知道b是首元素地址,那么*b就是首元素的内容了*(b+1)也就是第二个元素的内容了。
printf("*b=%c,*(b+1)=%c\n", *b, *(b + 1));
return;
}
你有耐性看完么,虽然技术不咋地,但是我们仍然的需要努力。三维数组或者更多维的数组都是一样的,我们只需要把数组名当做变量最近的那个[]方括号里面内容的地址就行了。比如char a[30] = "add";a代表的首元素地址char b[3][30]={"abc","bcd","ddd"},
b代表的是最近方括号是谁?是行,那么b代表的就是行的地址,三维的话,不知道叫啥,姑且就叫栋吧,就是栋的地址。然后在进行推导。
在主函数中调用它
验证结果截图:
886了,下次见。