免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: lunight

[函数] 高手问题:一个数组和函数地址的问题 [复制链接]

论坛徽章:
0
发表于 2006-09-19 11:33 |显示全部楼层
如果temcode是一个数组名时
printf("The address is %p\n", &temcode);
printf("The address is %p\n", temcode);
的结果是一样的,从这个角度看,
((void (*)(void)) &temcode )()
((void (*)(void)) temcode )()
都一样。

论坛徽章:
0
发表于 2006-09-19 11:49 |显示全部楼层
数组和指针还是有区别的,char ss[20] =" ";这里ss代表着数组的首址,&ss代表着&ss[0],所以应该是一样的
而char *ss = " ";中ss代表着常量的首址,&ss代表着放这个首址的地址。
还有下面一句应该有问题:
memcpy(temcode,code,sizeof(code)); 中应该sizeof(code) ==4

论坛徽章:
0
发表于 2006-09-19 15:17 |显示全部楼层
原帖由 neo_yang 于 2006-9-19 11:49 发表
数组和指针还是有区别的,char ss[20] =" ";这里ss代表着数组的首址,&ss代表着&ss[0],所以应该是一样的
而char *ss = " ";中ss代表着常量的首址,&ss代表着放这个首址的地址。
还 ...


你是对的,这句有问题,不能用sizeof(),应该直接传数组的大小

或者还有用sizeof ()的用法?

不过,&ss代表着&ss[0],我不是很理解,ss 不能代表ss[0]吧

[ 本帖最后由 lunight 于 2006-9-19 15:37 编辑 ]

论坛徽章:
0
发表于 2006-09-19 15:23 |显示全部楼层
数组做参数传入函数内,实际上是传递的指针,那么在函数内做调用函数memcpy(temcode,code,sizeof(code));实际上只是把code中四个字节的内容拷贝给temcode.

论坛徽章:
0
发表于 2006-09-19 15:31 |显示全部楼层
原帖由 coldwarm 于 2006-9-19 11:33 发表
如果temcode是一个数组名时
printf("The address is %p\n", &temcode);
printf("The address is %p\n", temcode);
的结果是一样的,从这个角度看,
((void (*)(void)) &temcode  ...


哈哈这么理解倒是满聪明的,不过fun==&fun的原因是不是和&temcode ==temcode 一样,是因为它们都是常数了,常数的地址被设成了他本身?(如版主所说)

论坛徽章:
0
发表于 2006-09-19 16:32 |显示全部楼层
本来编译应该对&array_name, 和&func_name给出错误。常数在数据区不存在,没有地址。

但编译照顾了错误的写法(或有别的原因?)

论坛徽章:
0
发表于 2006-09-20 12:24 |显示全部楼层
原帖由 思一克 于 2006-9-19 16:32 发表
本来编译应该对&array_name, 和&func_name给出错误。常数在数据区不存在,没有地址。

但编译照顾了错误的写法(或有别的原因?)


当 array_name 数组对象是一个左值的时候(通过定义产生的数组都是一个左值对象),可以对其进行取址运算。取址运算 &array_name 的结果是一个指向数组这个对象的指针。在一般情况下(非 sizeof 或者 & 的操作数),数组会自动转换为指向数组第一个元素的指针,所以 array_name 和 &array_name[0] 是等价的。需要注意的是:array_name (或  &array_name[0])与 &array_name 是不等价的——它们仅在数值上相等,但是类型不同。

在 C 语言中,对函数进行取址运算是标准的规定,运算的结果是指向函数的指针(函数的地址)。在 C++ 中函数是左值,所以对函数取址就更是理所当然的了。另外,根据标准的规定函数可以自动转换为指向函数的指针,所以 &func_name 和 func_name 是等价的。

数组和函数的不可改变性表现在:通常情况下,数组或者函数都被转换为指针使用,是右值,所以即使给数组名或者函数名赋值,实际改变不是数组对象或者函数本身,而是一个转化之后的右值——而(非类对象的)右值是不可被改变的。也就是说,对数组或者函数进行赋值是非法的操作。只能通过改变数组元素的方式来使数组对象发生改变。

经常看到把不能对数组名进行改变的原因归于“数组名是一个常量”这种说法,这是不正确的。“常量(或常数)”这个概念在标准中是有明确规定的。由于不存在数组类型的常量,所以数组名成为常量的唯一可能是作为指针类型出现。指针表达的是一个地址值。在标准中有“地址常量”这个说法:静态对象以及函数的地址是一个地址常量。因此,只有在一个数组是静态数组的时候,数组名代表的地址才是一个常量;否则,数组名不能作为常量使用。

当数组名作为指针类型使用的时候,由于这个指针值不会也不能发生变化,即指针的指向不变,所以在这种情况下可认为“数组名是一个常量指针”。除非是一个静态数组,否则不应该认为“数组名是一个常量”。

论坛徽章:
0
发表于 2006-09-20 12:27 |显示全部楼层
...

[ 本帖最后由 whyglinux 于 2006-9-20 12:36 编辑 ]

论坛徽章:
0
发表于 2006-09-20 13:01 |显示全部楼层
数组名字是常量。

在数据区没有占地方,在代码的立即数作为指令的一部分的名字都是常量。

比如a = 12345;  
b = 'c';
c = "123456"  ( 串的地址给C)

数组名,函数名和12345一样。

至于调用作为参数转换成什么(比如指针),和他本身是常量无关。

论坛徽章:
0
发表于 2006-09-20 14:32 |显示全部楼层
To 思一克

>> 数组名字是常量。
>> 在数据区没有占地方,在代码的立即数作为指令的一部分的名字都是常量。

你指的是静态数组吧。你试过非静态数组的情况吗?在这种情况下数组名也是立即数吗?我在上面已经对这两种情况下数组名是否是常量的情况最了区分说明。

下面的 C 程序也可证明“数组名是常量”这种观点的错误性:
  1. int main( void )
  2. {
  3.   int array[10];
  4.   static int* p = array;

  5.   return 0;
  6. }
复制代码

我用 gcc 编译的时候在指针 p 定义的一句出现了下列错误(注意要按照 C 程序编译,不要作为 C++ 程序编译,因为 C++ 的初始化非常灵活,从中看不到错误出现):
  1. error: initializer element is not constant
复制代码

如果把其中的数组定义为静态数组,就没有任何问题了。

诸如 "123456" 这样的字符串具有静态存储性质,是一个静态字符数组,也可以作为地址常量使用。

不要认为不能修改的就是常量。比如用 const 修饰的变量不能被修改,但是这样的变量在 C 中不是常量;(int)x 这样的类型转化的结果不能被修改,但是 (int)x 不是常量; x + y 这样的表达式的值不能被修改,而 x + y 也不是常量,等等。

在 C 语言中,一个对象能否被修改取决于它是否是一个“可修改的左值”。数组不是一个可修改的左值,一般的常量、(int)x、 x + y 等都是右值,都是不可以改变的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP