主题:一个怪程序
林杰杰
[专家分:8970] 发布于 2003-08-22 02:08:00
这是一个在别人的书里摘下的程序,它的结果有些怪。不知道有没有人知道哪里怪和怎么怪??
char ga[]="abcdefghijklmn";
void my_array_func(char ca[10]){
printf(" addr of array param = %#x \n",&ca);
printf(" addr (ca[0]) = %#x \n",&(ca[0]));
printf(" addr (ca[1]) = %#x \n",&(ca[1]));
printf(" ++ca = %#x \n\n",++ca);
}
void my_pointer_fun(char *pa){
printf(" addr of ptr param = %#x \n",&pa);
printf(" addr (pa[0]) = %#x \n",&(pa[0]));
printf(" addr (pa[1]) = %#x \n",&(pa[1]));
printf(" ++pa = %#x \n\n",++pa);
}
main(){
printf(" addr of global array = %#x \n",&ga);
printf(" addr (ga[0]) = %#x \n",&(ga[0]));
printf(" addr (ga[1]) = %#x \n",&(ga[1]));
my_array_func(ga);
my_pointer_fun(ga);
}
以上是程序,如果有人知道的话,麻烦告诉我。先谢了。
回复列表 (共18个回复)
11 楼
林杰杰 [专家分:8970] 发布于 2003-08-26 13:02:00
对于13和14楼的程序,相信大家都可以知道,a是"等于"&a的。但是,我想问一下,既然a是一个指针,代表的是一个地址,而取a的地址,居然是a指向的地址。
这是什么意思呢??难道说,a既保存了数组的首地址,又保存了a自己的地址吗?
我还是那句,这是一个未定义行为,由编译器决定怎么做。
12 楼
悠闲 [专家分:280] 发布于 2003-08-26 21:07:00
int a[]; a的值和&a是相同的.
但是两个值要分别赋给不同类型的指针.
13 楼
好好学习 [专家分:30] 发布于 2003-08-26 21:24:00
我想是不是可以这样理解a(a是数组名)与&a与&a[0]三者:
a:是数组名在程序中代表数组的首地址;
&a:这里是取数组a的地址并不是取a本身的地址;
&a[0]:这是取数组第一元素a[0]的地址;
这三者所代表的或取德的都是同一地址。
这问题搞的我晕晕的!
14 楼
denisity [专家分:0] 发布于 2003-08-27 00:26:00
但是
char a[]="abkjsdfj";
void fn(char ca[])
{
printf(" addr of array ca = %#x \n",ca);/* ca指实参a(数组a的首地址),即ca=&a[0]=a; */
printf(" addr of array &ca = %#x \n",&ca);/* 此处&ca指新创建的指针变量ca的地址值. ca!=&ca */
printf(" addr (ca[0]) = %#x \n",&(ca[0]));
printf(" addr (ca[1]) = %#x \n",&(ca[1]));
printf(" ++ca = %#x \n\n",++ca);
}
void main()
{
printf(" addr of array a[] = %#x \n",a);
printf(" addr of array &a = %#x \n",&a);
fn(a);
}
addr of array a[] = 0x422a30
addr of array &a = 0x422a30
addr of array ca = 0x422a30
addr of array &ca = 0x12ff30
addr (ca[0]) = 0x422a30
addr (ca[1]) = 0x422a31
++ca = 0x422a31
15 楼
林杰杰 [专家分:8970] 发布于 2003-08-27 02:09:00
To denisity:
在你的程序里,我想你要说的问题应该是函数fn()里ca!=&ca的问题吧。
K&R的名著中说到,作为函数定义的形式参数,char s[]和char* s是一样的。
不过,这只用于函数定义的形式参数!
也就是说,无论你在fn()中用的是char ca[]还是char *ca,编译成可执行代码时,都是一样的。这时的char ca[]中的ca是一个变量,而不是一个常量!因为它和char* ca相同。以下程序完全可以执行:
#include "stdio.h"
char p[]="abcdefgh";
void print(char tp[]){
while((*tp)!='\0'){
printf("%c",*tp);
tp++;
}
}
int main(void){
print(p);
return 0;
}
注意,在你的程序中的全局数组中的a是一个常量,a++不合法。
在实参a传值给形式参数cp时,要有一个值保存cp。所以cp!=&cp。这部分内容看meteor135的话,那里有很清楚的说明。但你的a又是“等于”&a的。这是作为形参和原来的数组的不同。
谢谢大家对这个帖子的关心,不过这个帖子现在也未免太长了吧……能不能……
16 楼
网事 [专家分:180] 发布于 2003-08-27 17:40:00
看了楼主的贴我已经将自已那些不确定和错误贴子删掉,我又查了些资料和做了些实验,为了叙述方便我将楼主的问题重新进行了定义,现将自已的结果贴出了给大家交流:
1、关于a和&a的区别
#include <stdio.h>
int main(void)
{
int a[20];
int *p1; //声明一个指向整型变量的指针变量p1
int (*p2)[20];//声明一个指向数组的指针变量p2
p1 = a;//p1指向数组a的第0个元素
p2 = &a;//p2指向一个有20个元素的数组a
printf("a = %d\n",sizeof(*p1));//p1所指向的类型为一个整型变量输出为:4
printf("&a = %d\n",sizeof(*p2));//p2所指向的类型为一个有80个元素整型数组为:80
printf("&a = %d\n",sizeof(*(&a));//&a指向数组的指针,和上边那条语句一样说明其为指向一个有20个元素的数组,输出为80
getchar();
return 0;
}
如果让p1 = &a是非法的,因为p1是指向整型变量的指针,而&a是一个数组类型的指针,它们不是同一类型所以不能互相赋值。为什么一些早期编译器(tc2.0)能编译成功,是因为早期的编译器没有数组指针的这个概念,所以可以顺利赋值。现在的编译器(bc6++,dev c++4.0)这样赋值是编译不过去的,它们会提示类型不匹配。
结论:数组名a是一个指向数组元素的指针,它指向第0个数组元素,&a是一个指向整个数组的指针。
2、关于数组类型在函数形参中的声名
当数组在函数中作为形参定义时,C语言把作为形参的数组定义转换为指针定义,举个列子:
int function(char *s)
{
.......
}
int function(char s[])
{
......
}
这两个定义函数的方法是一样的.
17 楼
林杰杰 [专家分:8970] 发布于 2003-08-27 18:11:00
To 好好学习:
打7楼开始都是在回答你的问题,你说你想给谁评分?
18 楼
好好学习 [专家分:30] 发布于 2003-08-27 22:33:00
还是楼主评分吧,我的问题也是由你们的帖子才想到的。
等我以后做楼主时在给你们评分! 嘿嘿!
我来回复