/*
============================================================================
Name : TeatArr.c
Author : lf
Version :
Copyright : Your copyright notice
Description : 二维数组的认识以及其表示元素的两种方式
备注说明
1 要理解二维数组的存储方式.
2 实际上利用a[i][j]的方式并不"正统",但这靠近我们的
常识一些,更本质和应该的还是利用指针和数组名.
一个二维数组,比如:
int array[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
它在内存中存在方式如下:
0X00F8FE4C 1 2 3 4
0X00F8FE5C 5 6 7 8
0X00F8FE6C 9 10 11 12
即:
从0X00F8FE4C地址开始存放了 1 2 3 4
从0X00F8FE5C地址开始存放了5 6 7 8
从0X00F8FE6C地址开始存放了9 10 11 12
参考资料:
http://blog.csdn.net/iu_81/article/details/1782642
http://www.jb51.net/article/54220.htm
Thank you very much
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
// test0();
// test1();
test2();
// test3();
return EXIT_SUCCESS;
}
/**
* 一维数组的两种表达方式
* int *p=&a
* 指针p执行了数组a的首元素.
* 又因为*p是取内容,所以*(p+N)
* 取的就是第N个元素的内容
*/
void test0(){
int a[5]={0,1,2,3,4};
//第一种方式:下标表示法
int i=a[2];
printf("i=%d\n",i);
//第二种方式:指针表示
int *p=&a;
int j=*(p+2);
printf("j=%d\n",j);
printf("==========\n");
//在一维数组中数组名就是首元素的地址
//所以a和&a[0]是等值的.
//但是注意&a虽然值和它们两个相等,但是它是
//代表整个数组的块地址的起始值.
//这点通过sizeof()可以看出来
printf("a=%x,sizeof(*a)=%d\n",a,sizeof(*a));
printf("&a[0]=%x,sizeof(*&a[0])=%d\n",&a[0],sizeof(*&a[0]));
printf("&a=%x,sizeof(*&a)=%d\n",&a,sizeof(*&a));
printf("==========\n");
}
/**
* 将二维数组a[3][4]看作一维数组a[3]
* 一维数组a[3]中每个元素又是一个一维数组.
* 那么&a[i]表示某一行的地址块的首地址
* 所以sizeof(*&a[0])=4*4=16
* 即sizeof(a[0])=4*4=16
* &a[i]是个地址,所以sizeof(&a[0])=4或者8字节
*
* 在一维数组:
* int c[3]={0,1,2};
* 中数组名c就是第一个元素的首地址,所以*c=0即取出了第一个元素.
* 同样的道理a[i]也是一个一维数组,那么*a[i]就是取出了第i行的
* 第一个元素.比如*a[0]=0
*/
void test1() {
int i=9527;
int *p=&i;
//p=8d49c90c,&p=8d49c900,*&p=8d49c90c,*p=9527
//p是p指向的内存单元,&p是p本身的内存单元,
//*&p取出p中所指向的内存单元就是p(和第一个值一样)
//*p取出指针指向的内存单元的值
printf("p=%x,&p=%x,*&p=%x,*p=%d%x\n",p,&p,*&p,*p);
int c[3]={0,1,2};
//*c=0,c=8d49c8f0,&c=8d49c8f0,*&c=8d49c8f0
//*c好理解,取出了数组中的第一个元素
//c是数组第一个元素的首地址,这个也好理解
//&c是整个数组的地址块的首地址.
//*&c是什么意思呢?
//我们习惯简单地说:由于*和&抵消了,所以*&c就是c.
//从数值上看也确实是这样.
//*&c还可以怎么理解呢?
//注意上面的例子:
//int i=9527;
//int *p=&i;
//*&p的值就是p,即*&p的值和p是一样的.
//其实此处是非常相似的,可以这么看:
//int *p=&c;
//就是说把c的地址保存在了p那个内存单元里面
//那么*&p和p是一样的均为整个数组c的地址块的首地址
//所以*&c可以这么理解:
//第一步:&c取出了c的地址放到了某个内存单元里面
//第二步:*&c即从某个内存单元里取值,取出的值当然是c的地址
//这个过程和上面是一样的.只是没有用一个指针变量明确存放c的地址而已
printf("*c=%d,c=%x,&c=%x,*&c=%x\n",*c,c,&c,*&c);
printf("===========\n");
int a[3][4] = { { 0, 1, 2, 3 },
{ 4, 5, 6, 7 },
{ 8, 9, 10, 11 } };
//&a[0]和a[0]的数值相等,但是含义不同.
//&a[0]是整个行的块地址的起始地址
//a[0]是这行第一个元素的首地址
//*a[0]取得了这行的第一个元素的值
//这里把a[0]看做一个一维数组就很好理解了.
printf("&a[0]=%x,a[0]=%x,*a[0]=%d\n",&a[0],a[0],*a[0]);
printf("sizeof(*&a[0])=%d,,sizeof(a[0])=%d,sizeof(&a[0])=%d,sizeof(*a[0])=%d\n",
sizeof(*&a[0]),sizeof(a[0]),sizeof(&a[0]),sizeof(*a[0]));
printf("===========\n");
}
/**
* 二维数组的认识
*
* 关于二维数组的指针表示方式,简述如下:
* 二维数组的每个元素是一个一维数组.
* 这个是认识和分析二维数组的基础和核心
*
* 一个二维数组,比如:
* int array[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
* 它在内存中存在方式如下:
* 0X00F8FE4C 1 2 3 4
* 0X00F8FE5C 5 6 7 8
* 0X00F8FE6C 9 10 11 12
* 即:
* 从0X00F8FE4C地址开始存放了 1 2 3 4
* 从0X00F8FE5C地址开始存放了5 6 7 8
* 从0X00F8FE6C地址开始存放了9 10 11 12
* 从本质上而言二维数组的元素在内存中还是线性地按序存放的.
*
* 把二维数组a[3][4]可以看成是有3个元素的一维数组a[3]:
* {0X00F8FE4C,0X00F8FE5C,0X00F8FE6C}
* 注意的问题:
* 0 这个一维数组a[3]是抽象的,不是很具体
* 1 a[3]每个元素都是一个行地址.
* a[3]每个元素的值就是每行即每个一维数组的首地址.
* 2 这个数组的首地址就是0X00F8FE4C!!!!!
* 同理第2个元素的地址就是0X00F8FE5C,其值也是这个值.
* 3 二维数组a[3][4]看成是有3个元素的一维数组a[3].
* 这里的行数为3得到了体现,那么列数4在哪里体现的呢?
* 这个a[3]的步长为4个整型长度即16字节.
* 比如int b[3]={0,1,2};
* 因为它每个元素都是int类型的,所以它的步长就是4个字节
* b代表第一个元素的地址,b+1代表了第二个元素的地址;
* 从b到b+1移动了4个字节.
* 所以这里的a[0]到a[1]移动了4*4=16个字节
*
*
* 利用下标表示法:
* 每个元素的地址用下标表示法为&a[i]其值是*&a[i]即a[i]
*
* 利用指针表示法(数组名表示法):
* 每个元素的地址表示为a+i,其值为*(a+i)
*
* 所以可以说:
* &a[i]与a+i等价
* a[i]与*(a+i)等价
*
* 这只是两种不同表达方式的差异罢了,获取到的值当然是一样的.
* 这两种方式即a[i]和*(a+i)都获取到了a[3]每个元素的值
* 也是每个一维数组的起始地址.
*
* 小结:
* 获取每个一维数组里第j个元素的地址的两种方式就分别是:
* a[i]+j和*(a+i)+j
* 获取每个一维数组里第j个元素的内容的两种方式就分别是:
* *(a[i]+j)和*(*(a+i)+j)
* 所以可以说:
* a[i]+j和*(a+i)+j等价,都是用来取地址的
* *(a[i]+j)和*(*(a+i)+j)等价,都是用来取内容的
*
* 最后,再次提醒a[3]每个元素的地址及其内容是一样的.
*/
void test2(){
int a[3][4] = { { 0, 1, 2, 3 },
{ 4, 5, 6, 7 },
{ 8, 9, 10, 11 } };
//获取a[3]每个元素地址和其对应的内容的两种方式:
//&a[i],a[i]和a+i,*(a+i)
printf("&a[0]=%x,a[0]=%x <==> a+0=%x,*(a+0)=%x\n",&a[0],a[0],a+0,*(a+0));
printf("&a[1]=%x,a[1]=%x <==> a+1=%x,*(a+1)=%x\n",&a[1],a[1],a+1,*(a+1));
printf("&a[2]=%x,a[2]=%x <==> a+2=%x,*(a+2)=%x\n",&a[2],a[2],a+2,*(a+2));
printf("==========\n");
//访问第二行的第三个元素:
printf("a[1]+2=%x,*(a[1]+2)=%d\n",a[1]+2,*(a[1]+2));
printf("*(a+1)+2=%x,*(*(a+1)+2)=%d\n",*(a+1)+2,*(*(a+1)+2));
printf("==========\n");
}
/**
* 二维数组的两种表达方式
*
* 利用下标方式访问i行j列的数据很简单:a[i][j]
*
* 如果用指针的方式又该是怎么样呢?
* 第一步:找到行
* 从test2()中我们已经知道了行地址是*(a+i)
* 第二步:找到列
* 找到了行再找列就简单多了,偏移j个单位就行
* 得到地址为*(a+i)+j
* 所以取值为*(*(a+i)+j);
*
*/
void test3(){
int a[3][4] = { { 0, 1, 2, 3 },
{ 4, 5, 6, 7 },
{ 8, 9, 10, 11 } };
//第一种方式:下标表示法
int i=a[2][3];
printf("i=%d\n",i);
//第二种方式:指针表示
int j=*(*(a+2)+3);
printf("j=%d\n",j);
}
///**
// * 这是以前我土鳖的认识方法。。。
// * 也就不删了。。。
// *
// *
// * 二维数组的认识
// *
// * 关于二维数组的指针表示方式,简述如下:
// * 二维数组的每个元素是一个一维数组.
// * 比如此处的a[3][4]可以看成是有3个元素的一维
// * 数组,每个元素又是具有4个元素的一维数组.
// * 所以此时可把二维数组a[3][4]看作一维数组a[3]
// * 这个一维数组有三个元素,每个元素又是一个一维数组.
// * 在此打印每行的地址:
// * &a[0]=28feb0
// * &a[1]=28fec0
// * &a[2]=28fed0
// * 可以看到每行的地址相差4*4=16
// * 但是为什么
// * a[0]=28feb0
// * a[1]=28fec0
// * a[2]=28fed0
// * 也打印出来了每行的地址???
// * 这个很简单,在test1()中已经进行了说明:
// * &a是一个地址,再执行*&a还是得到这个地址.
// * 即&a[0]=*&a[0]在数值上也等于a
// * 所以&a[i]与*(&a[i])和a[i]是同一回事!!!
// *
// * 因为a是指向第一行的地址,所以a+1代表第二行的地址,a+2代表第三行的地址
// * 所以&a[i]与a+i是同一回事!!
// *
// * 综上所述:
// * 在二维数组a中
// * &a[i]与*(&a[i])和a[i]还有a+i是等价的
// *
// * 由此可以看到两条演变的路线:
// * &a[i]-->*&a[i]-->a[i]
// * &a[i]-->*&a[i]-->*(&a[i])-->*(a+i)
// *
// */
//void test2(){
//
//
// int a[3][4] = { { 0, 1, 2, 3 },
// { 4, 5, 6, 7 },
// { 8, 9, 10, 11 } };
// //打印二维数组每一行的首地址.&a[i]与a+i等价
// printf("&a[0]=%x,a+0=%x\n",&a[0],a+0);
// printf("&a[1]=%x,a+1=%x\n",&a[1],a+1);
// printf("&a[2]=%x,a+2=%x\n",&a[2],a+2);
//
//
// printf("&a[0]=%x,a[0]=%x,*(a+0)=%x\n",&a[0],a[0],*(a+0));
// printf("&a[1]=%x,a[1]=%x,*(a+1)=%x\n",&a[1],a[1],*(a+1));
// printf("&a[2]=%x,a[2]=%x,*(a+2)=%x\n",&a[2],a[2],*(a+2));
//
//
// printf("==========\n");
//}
//**
// * 这是以前我土鳖的认识方法。。。
// * 也就不删了。。。
// * 二维数组的认识
// *
// * 关于二维数组的指针表示方式,简述如下:
// * 二维数组的每个元素是一个一维数组.
// * 这个是认识和分析二维数组的基础和核心
// *
// * 一个二维数组,比如:
// * int array[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
// * 它在内存中存在方式如下:
// * 0X00F8FE4C 1 2 3 4
// * 0X00F8FE5C 5 6 7 8
// * 0X00F8FE6C 9 10 11 12
// * 即:
// * 从0X00F8FE4C地址开始存放了 1 2 3 4
// * 从0X00F8FE5C地址开始存放了5 6 7 8
// * 从0X00F8FE6C地址开始存放了9 10 11 12
// *
// * 把二维数组a[3][4]可以看成是有3个元素的一维数组a[3]
// * 利用下标表示法:每个元素的地址用下标表示法为&a[i]其值是*&a[i]即a[i]
// * 利用指针表示法(数组名表示法):每个元素的地址表示为a+i,其值为*(a+i)
// * 所以可以说:
// * &a[i]与a+i等价
// * a[i]与*(a+i)等价
// * 这只是两种不同表达方式的差异罢了,获取到的值当然是一样的.
// * 这两种方式即a[i]和*(a+i)都获取到了a[3]每个元素的值
// * 也是每个一维数组的起始地址
// *
// * 每个元素的地址用下标表示法为&a[i]其值是*&a[i]即a[i]
// * 我们可以发现&a[i]和a[i]在数值上是相等的.
// * 这是为什么呢?可以这么理解:
// * 还是要从二维数组的本质说起:
// * 1 二维数组的每个元素是个一维数组
// * 2 把二维数组a[i][j]可以看成是有i个元素的一维数组a[i]
// * 那么a[0],a[1]....a[i]都是一维数组
// * 既然a[i]是一维数组,那么&a[i]是一维数组地址块的首地址
// * a[i]是一维数组第一个元素的首地址.
// * 所以他们在数值上是相等的,但是含义不同.
// *
// * 每个元素的地址表示用指针和数组名表示为a+i,其值为*(a+i)
// * 我们可以发现a+i和*(a+i)在数值上是相等的
// * int array[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
// * 它在内存中存在方式如下:
// * 0X00F8FE4C 1 2 3 4
// * 0X00F8FE5C 5 6 7 8
// * 0X00F8FE6C 9 10 11 12
// * 可以明确的一点:这一块内存地址是连续的,即每个元素之间也是紧挨着存放的.
// * 那么a[3]可以看成{0X00F8FE4C,0X00F8FE5C,0X00F8FE6C}
// * 当然这个数组的首地址也就是0X00F8FE4C
// * a+i表示第i个元素的地址.
// * *(a+i)是其对应的值
// *
// *
// * 那么获取每个一维数组里第j个元素的地址的两种方式就分别是:
// * a[i]+j和*(a+i)+j
// * 那么获取每个一维数组里第j个元素的内容的两种方式就分别是:
// * *(a[i]+j)和*(*(a+i)+j)
// * 所以可以说:
// * a[i]+j和*(a+i)+j等价
// * *(a[i]+j)和*(*(a+i)+j)等价
// */
//void test2(){
//
// int i=9527;
// int *p=&i;
// printf("&i=%x,p=%x,&p=%d\n",&i,&(*p),*p);
//
// int a[3][4] = { { 0, 1, 2, 3 },
// { 4, 5, 6, 7 },
// { 8, 9, 10, 11 } };
//
// //获取a[3]每个元素地址和其对应的内容的两种方式:
// //&a[i],a[i]和a+i,*(a+i)
// printf("&a[0]=%x,a[0]=%x <==> a+0=%x,*(a+0)=%x\n",&a[0],a[0],a+0,*(a+0));
// printf("&a[1]=%x,a[1]=%x <==> a+1=%x,*(a+1)=%x\n",&a[1],a[1],a+1,*(a+1));
// printf("&a[2]=%x,a[2]=%x <==> a+2=%x,*(a+2)=%x\n",&a[2],a[2],a+2,*(a+2));
// printf("==========\n");
//
// //访问第二行的第三个元素:
// printf("a[1]+2=%x,*(a[1]+2)=%d\n",a[1]+2,*(a[1]+2));
// printf("*(a+1)+2=%x,*(*(a+1)+2)=%d\n",*(a+1)+2,*(*(a+1)+2));
//
// printf("==========\n");
//}
二维数组的认识及其表示元素的两种方式
最新推荐文章于 2021-08-17 12:14:16 发布