各位帮帮忙,小女子谢谢啊~~~~~~~~~~~~~~~~~~~~
若有说明int a[4][4],*p=a[0];则对数组元素a[i][j]之值的正确引用是
A *(*(p+i)+j) B *(p[i]+j)
C p[i*4+j] D *(a[i]+j)
求解释,~~~~(>_<)~~~~
[解决办法]
不做强转,题目编译能过?
[解决办法]
你可以编个程序测试下。
[解决办法]
a在内存中的状态是按顺序 a[0][0], a[0][1], a[0][2], a[0][3], a[1][0], ..., a[3][3],
a[0]获得的是指向a[0][0]的指针,把它赋值给p后,想得到指向a[i][j]的指针就可以写p + i * 4 + j,获得其内容就是*(p + i * 4 + j)等价于p[i * 4 + j]
[解决办法]
我编译过,cd都可以
[解决办法]
a[i]是一个行指针,其值为:第i个一维数组的首元素的地址
然后+j, 即a[i][j]
a[i][j] 反汇编估计是这样的:两步骤:1,定位到第i个一维数组的首元素的地址,2:偏移
所以cd都是对的
不对请指出
另外:楼主可以自行测试。。我没有测试
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”
提醒:
“学习用汇编语言写程序”
和
“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!
不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
1: int a[4][4];2: int *p=a[0];3: int i=2;j=3,v;4: void main() {//0401000 55 push ebp//0401001 8B EC mov ebp,esp//0401003 83 EC 40 sub esp,40h//0401006 53 push ebx//0401007 56 push esi//0401008 57 push edi5: v=a[i][j];//0401009 A1 34 E0 40 00 mov eax,[i (0040e034)]//040100E C1 E0 04 shl eax,4//0401011 8B 0D 38 E0 40 00 mov ecx,dword ptr [j (0040e038)]//0401017 8B 94 88 00 EB 40 00 mov edx,dword ptr [eax+ecx*4+40EB00h]//040101E 89 15 40 EB 40 00 mov dword ptr [v (0040eb40)],edx6: //v=*(*(p+i)+j);//A error C2100: illegal indirec7: //v=*(p[i]+j); //B error C2100: illegal indirec8: v=p[i*4+j]; //C//0401024 A1 34 E0 40 00 mov eax,[i (0040e034)]//0401029 8B 0D 38 E0 40 00 mov ecx,dword ptr [j (0040e038)]//040102F 8D 14 81 lea edx,[ecx+eax*4]//0401032 A1 30 E0 40 00 mov eax,[p (0040e030)]//0401037 8B 0C 90 mov ecx,dword ptr [eax+edx*4]//040103A 89 0D 40 EB 40 00 mov dword ptr [v (0040eb40)],ecx9: v=*(a[i]+j); //D//0401040 8B 15 34 E0 40 00 mov edx,dword ptr [i (0040e034)]//0401046 C1 E2 04 shl edx,4//0401049 A1 38 E0 40 00 mov eax,[j (0040e038)]//040104E 8B 8C 82 00 EB 40 00 mov ecx,dword ptr [edx+eax*4+40EB00h]//0401055 89 0D 40 EB 40 00 mov dword ptr [v (0040eb40)],ecx10: }
[解决办法]
现行国内教程中有大量这样的题目,难为了许多人。
现行国内教程又说不清数组与指针的关系,这样的题目真的就成为学生的拦路虎了。
我来说一下:
基本概念
1.数组名是&数组名[0]的缩写(不是所有场合下,此处不深入说),这转化成一种纸上演算:数组名==== &数组名[0]
2.*与&是一对逆操作:&--取地址、*--按地址取值,所以有*&对象====对象,&*地址====地址
3.地址前的*与地址(数组名)后[0] 存在互换关系
下面使用这些概念解释LZ的问题:
int a[4][4],*p=a[0];
A *(*(p+i)+j)
B *(p[i]+j)
C p[i*4+j]
D *(a[i]+j)
==================
第一行:a是二维数组,四行四列; p指向了&a[0] [0]--是元素的地址
第二行A:p+i是地址+偏移--仍是地址,*(p+i)是取地址的值--即int数值,(*(p+i)+j)是数值,*(*(p+i)+j)则错了--不能*数值
第三行B:同A--p[i]是*(p+i)另一表述法(用上边的概念可以推演出来)
第四行C:i*4是指第 i行前共有的元素数量,j是指第i行中第j列元素(即a[i][j])前元素数量,则i*4+j是a[i][j]这个元素前的元素个数,p[i*4+j]即这个元素的值
!!!!LS有人将4理解为32位系统中sizeof(int)值,有误----这个4是“四列”
第五行D:*(a[i]+j)====*(&a[i][0]+j)====*(&a[i][j])====*&a[i][j]====a[i][j]
指针(地址)表达式是C语言的脊梁骨,立则C立