数组指针的问题.请教了.谢谢

Miudy 2007-10-30 11:41:01
main()
{
int i,a[2]={1,2} ,b[2][2]={1,2,3,4};
printf("%d,%d,%d,%d\n",*a,&a,a,&a[0]);
printf("%d,%d,%d,%d\n",*b,&b,b,&b[0]);


getch();
}
 结果输出     1, -62 ,-62,-62
          -58,-58,-58,-58 
问题一:
    *a 为什么输出的是a[0]的值 而不是数组a的首地址.而*b是输出的却是数组b的首地址?
    既然 a,b代表的都是数组的首地址,假设*是取内容运算符,为啥两个不同啊?  

问题二: 地址为啥是负的,这个问题有可能小白了(当时微机原理没学好). 

延伸问题,上面代码改如下

main()
{
  int i,a[2]={1,2} ,b[2][2]={1,2,3,4},*pa,*pb;
  pa=a;
  pb=b;

  printf("%d,%d,%d,%d\n",*a,&a,a,&a[0]);
  printf("%d,%d,%d\n",*pa,pa,&pa);
  printf("%d,%d,%d,%d\n",*b,&b,b,&b[0]);
  printf("%d,%d,%d\n",*pb,pb,&pb);

getch();

}
 输出结果:
  1,-66,-66,-66
  1,-66,-54,
  -62,-62,-62,-62
  1,-62,-52
  
  既然 pb=b; 那么输出的时候 *pb 应该与 *b一样,结果却不同..
  关于"*" 变量声明的时候是 :指针说明符号.
 而用在表达式时 如上面的printf("%d,%d,%d,%d\n",*a,&a,a,&a[0]); 教材上只是含糊的说了是:取内容运算符. 就没在解释.(真心不希望是教材的失误.那真误人子弟了)
既然是取内容运算符.那a是a[0]的首地址,b是b[0][0]的首地址, *a和 *b 的结果为啥一个是数值,一个是地址啊.不要说*b是取的b[0]的地址,也抛开宏观上的硬说b是个2维数组所以就这种结果.因为输出的时候 printf("%d,%d\n",b,&b[0]);都是-62 既然 b 代表地址,那*b还代表地址..想不通啊.. 我的微机和编译原理啊,看来要饿补了...

请教了.大虾门 ,谢谢了.

 
...全文
101 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
ajhao327 2007-10-31
  • 打赏
  • 举报
回复
刚才去搜了下,你可以去这里看下,也许有帮助http://blog.csdn.net/icdlan/archive/2006/10/23/1346563.aspx
ajhao327 2007-10-31
  • 打赏
  • 举报
回复
问题二: 地址为啥是负的?
这个问题因为你用的是%d输出,是int类型的数,只要地址的最高位为1就是负数,你如果改为%x输出就会是十六进制的地址值了。
关于问题一比较复杂,尤其是涉及到2维以上的数组,我也没怎么搞明白,能讲一点就是一点吧^_^
a其实是该数组的首地址,你可以将其看作一个指针,对其作*a运算其实就相当于a[0]了,所以*a = 1,但是之所以说数组比较特殊而不能完全看成指针来用是因为你如果查看a的地址,你会发现&a其实就是a[0]的地址,编译器不会给a分配空间来存放他,但是你如果申请一个指针,比如int *c = a,编译器就会给该指针本身申请一个空间来存放,那么&c != a,
简单点说对于一维数组你可以大致把a当作一个指针看。
但是对于2维以上数组,就比较复杂了,它与指针的区别就更加明显了,虽然自己会用算些,但是没有一个原理上的理解,就不给你瞎讲了,留给其他牛人给你说吧。
baihacker 2007-10-31
  • 打赏
  • 举报
回复
main()
{
int i,a[2]={1,2} ,b[2][2]={1,2,3,4};
printf( "%d,%d,%d,%d\n ",*a,&a,a,&a[0]);
printf( "%d,%d,%d,%d\n ",*b,&b,b,&b[0]);


getch();
}
 结果输出     1, -62 ,-62,-62
          -58,-58,-58,-58 
问题一:
    *a 为什么输出的是a[0]的值 而不是数组a的首地址.而*b是输出的却是数组b的首地址?
    既然 a,b代表的都是数组的首地址,假设*是取内容运算符,为啥两个不同啊? 

a的类型是 int [2],忽略掉其中的2,类型为int [], 和int*等价, 结果明显
b的类型是 int [2][2], 忽略掉第一维的信息 int [][2], 和int (*)[2]等价,也就是把b看作一个指向二维数组的指针,*b的值就是这个数组的首地址了
问题二: 地址为啥是负的,这个问题有可能小白了(当时微机原理没学好).
有人回答了
////////////////////////////////////////////////////////////////////////////
main()
{
  int i,a[2]={1,2} ,b[2][2]={1,2,3,4},*pa,*pb;
  pa=a;
  pb=b;

  printf( "%d,%d,%d,%d\n ",*a,&a,a,&a[0]);
  printf( "%d,%d,%d\n ",*pa,pa,&pa);
  printf( "%d,%d,%d,%d\n ",*b,&b,b,&b[0]);
  printf( "%d,%d,%d\n ",*pb,pb,&pb);

getch();

}
 输出结果:
  1,-66,-66,-66
  1,-66,-54,
  -62,-62,-62,-62
  1,-62,-52
  
  既然 pb=b; 那么输出的时候 *pb 应该与 *b一样,结果却不同..
  关于"*" 变量声明的时候是 :指针说明符号.
 而用在表达式时 如上面的printf( "%d,%d,%d,%d\n ",*a,&a,a,&a[0]); 教材上只是含糊的说了是:取内容运算符. 就没在解释.(真心不希望是教材的失误.那真误人子弟了)
既然是取内容运算符.那a是a[0]的首地址,b是b[0][0]的首地址, *a和 *b 的结果为啥一个是数值,一个是地址啊.不要说*b是取的b[0]的地址,也抛开宏观上的硬说b是个2维数组所以就这种结果.因为输出的时候 printf( "%d,%d\n ",b,&b[0]);都是-62 既然 b 代表地址,那*b还代表地址..想不通啊.. 我的微机和编译原理啊,看来要饿补了...
//////////////////////////////////////////////////////////////
int i,a[2]={1,2} ,b[2][2]={1,2,3,4},*pa,(*pb)[2];
这样的就对了

你用一个int [2][2](或者 int [][2] int (*)[2])给int*赋值的时候有类型转换!
也就是把b的首地址重新解释为int*,当然*pb和*b不一样了...
ttlyfast 2007-10-31
  • 打赏
  • 举报
回复
问题一:
编译器生成的汇编代码如下


.file "test.c"
.section .rdata,"dr"
LC0:
.ascii "%d,%d,%d,%d\12 \0"
。。。。。。
。。。。。。


leal -32(%ebp), %eax //得到数组a的首地址也就相当于a
subl $72, %esp //分配数组和参数的空间
movl %eax, 16(%esp) //printf的第五个参数&a[0]
movl %eax, 12(%esp) //printf的第四个参数a
movl %eax, 8(%esp) //printf的第三个参数&a
movl $1, %eax //*a的结果存入
movl $1, -32(%ebp) //a[0] = 1
movl $2, -28(%ebp) //a[1] = 2
movl $1, -24(%ebp) //b[0] = 1
movl $2, -20(%ebp) //b[1] = 2
movl $3, -16(%ebp) //b[2] = 3
movl $4, -12(%ebp) //b[3] = 4
movl %eax, 4(%esp) //printf的第二个参数*a
movl $LC0, (%esp) //printf的第一个参数 串"%d,%d,%d,%d\12 \0"
call _printf //调用printf
movl $LC0, (%esp) //printf的第一个参数 串"%d,%d,%d,%d\12 \0"
leal -24(%ebp), %eax //&b[0] 存入
movl %eax, 16(%esp) //printf的第五个参数&b[0]
movl %eax, 12(%esp) //printf的第四个参数b
movl %eax, 8(%esp) //printf的第三个参数&b
movl %eax, 4(%esp) //printf的第二个参数*b
call _printf //调用printf


这里我们看到
1 &a[0] ,a ,&a 都被翻译成了数组a的首地址
  而a[0]被翻译成1
  因为 a即代表a数组的首地址我们看到汇编代码中并没有a的存在
  编译器遇到a时直接取a数组的首地址
  而a[0]代表数组a的第一个元素
  这里编译器做了优化 既把a[0]用1来代替

2 编译器把多维数组看成一维数组并按照"行优先"的顺序依次排列
  编译器内用一种简单的算法来完成多维数组到一维数组的转换
  而*b被解释为二维数组b的第一行的首地址 
  当然与数组b的首地址相同拉更多相关知识建议你去看看书上的
  多维数组部分

延伸问题:
    这个lz你自己去做实验 看结果
    要多动手哦 ~~
  
yyy6210 2007-10-31
  • 打赏
  • 举报
回复
问题一:
    *a 为什么输出的是a[0]的值 而不是数组a的首地址.而*b是输出的却是数组b的首地址?
    既然 a,b代表的都是数组的首地址,假设*是取内容运算符,为啥两个不同啊?  
---------------------------------------------------------------
菜鸟一个,可能解释的不对!

a是个一维数组,a代表数组的首地址,*a输出的是第一个元素的值
b是一个二维数组,b代表二维数组的首地址,b[0]代表一维数组的首地址。*b等同于b[0],而该地址又是整个数组的首地址。

wh_peng 2007-10-31
  • 打赏
  • 举报
回复
ding

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧