首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

各位帮帮忙,小女子多谢啊

2012-04-01 
各位帮帮忙,小女子谢谢啊~~~~~~~~~~~~~~~~~~~~若有说明int a[4][4],*pa[0]则对数组元素a[i][j]之值的正

各位帮帮忙,小女子谢谢啊~~~~~~~~~~~~~~~~~~~~
若有说明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都是对的

不对请指出

另外:楼主可以自行测试。。我没有测试


探讨
D是错的,a[i]+j,实际等于a[i+j]...是不是这样?

[解决办法]
我觉得对于这种问题,先在编译器上试下,然后自己有些思考,然后查下书,这样对于知识的理解就会更深
[解决办法]
学聪明了,,直接把题目写成小女子了。。。。


哈哈哈哈哈哈。。。

目前没看到详细且正确的答案。。。

答案是CD
[解决办法]
纠正一下,我犯了错误,还是基础不扎实

a[i]不是行指针,是数组名,

在表达式汇中,自动转位a[i]的首元素的地址

对于&a[i]才是获得行指针




探讨
a[i]是一个行指针,其值为:第i个一维数组的首元素的地址

然后+j, 即a[i][j]

a[i][j] 反汇编估计是这样的:两步骤:1,定位到第i个一维数组的首元素的地址,2:偏移

所以cd都是对的

不对请指出

另外:楼主可以自行测试。。我没有测试


引用:
D是错的,a[i]+j,实际等于a[i+j]...是不是这……

[解决办法]
探讨
a[i]就是数组名

[解决办法]
比如用二维的字符数组存放多个字符串:
char s[3][40]={"Hello","How are you?","I'm fine, thank you."};

那么 cout<<s[0]; 显示的是 Hello
cout<<s[1]; 显示的是 How are you?
cout<<s[2]; 显示的是 I'm fine, thank you.

说明 s[0]、s[1]、s[2]都是一个字符指针,即 char*,

s[0] 指向Hello中的字符“H”
s[1] 指向How中的字符“H”
s[2] 指向字符“I”

[解决办法]
A *(*(p+i)+j) 
B *(p[i]+j)
C p[i*4+j] 
D *(a[i]+j)

因为 *(p+i) 相当于 p[i],所以A\B是一样的。因为*(p+i)+j的结果是整型数据,所以再运用取内容运算符*是错误的。A B 都是错误的。

因为数组在内存中按行连续存储的,所以也可以按一维数组的形式来访问,所以C是对的

把a[i]看成p,选项D就变成了*(p+j),可转换成p[j],再把p换成a[i],就是a[i][j],所以D也是对的。

[解决办法]
严格来说只有D是对的,详细可以参考《C陷阱与缺陷》第三章3.1数组与指针45页。
由于未声明是32位系统故严格来说C不正确,中的i*4,4是32位系统int所占字节。
[解决办法]
探讨

严格来说只有D是对的,详细可以参考《C陷阱与缺陷》第三章3.1数组与指针45页。
由于未声明是32位系统故严格来说C不正确,中的i*4,4是32位系统int所占字节。

[解决办法]
探讨
不做强转,题目编译能过?

[解决办法]
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)


想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

C/C++ code
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立




热点排行