原创 C语言指针问题

2008-5-17 16:11 3304 4 4 分类: MCU/ 嵌入式

激烈讨论见: http://bbs.21ic.com/club/bbs/list.asp?boardid=11&page=1&t=2963283


俺觉得搞笑~~~



wrainp 发表于 2008-5-14 18:30 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

楼主: C语言指针问题


main()
{
  int a[5]={1,2,3,4,5};
   int *ptr=(int *)(&a+1);
   printf("\n%d,%d",*(a+1),*(ptr-1));
}

输出结果是多少?
  请解释一下原因...


computer00 发表于 2008-5-15 03:21 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

5楼: 看来不同的编译器处理结果不一样。


我在keil下编译,&a+1的结果就是a+1。要不要那个&都无所谓。


hotpower 发表于 2008-5-16 02:01 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

18楼: 不懂~~~只知道&a是变量a定位地址的数值


computer00 发表于 2008-5-16 02:06 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

19楼: 哈哈~~~你到keil下试下?结果发现a并不是一个变量,


而是一个常量,所以keil并不为它分配RAM空间,也就无所谓保存地址的问题。
编译器自己记住了a里面的值,并没有单独为a分配一个空间,所以在keil下,&a的值跟a的
值居然是一样的。本来也是,数组名是指针常量,编译器知道它的值是多少就行了,
没必要单独分配一个空间(实际上是放在程序段中了)来保存之,浪费空间。

这个跟函数名有点类似,函数名本来就是一个地址了,如果再取地址会怎样?
结果还是一样,返回的值还是函数地入口地址,而不是一个指向函数的指针
的地址。就算你在函数名前加100个&也是一样...


hotpower 发表于 2008-5-16 02:09 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

20楼: 哈哈~~~那是Keil C51倒塌的事情,Keil ARM/Cortex M3就大不同了



computer00 发表于 2008-5-16 02:24 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

21楼: 哈哈~~~大叔搞错了,&a不是保存的a的地址,它的值还是a...


不管是在C51下,还是CARM下,还是在VC下,我都试过,&a跟a的值是同一个。
也就是说,a本来就是一个指针,已经到尽头拉,再对它取地址,它只好耍无赖,
再对它取地址都无用了。但是对后面的加1操作却有着不同的做法。C51下&a+1是
只偏移一个int,而在VC下,却是5个int……



hotpower 发表于 2008-5-16 13:03 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

24楼: 哈哈~~~俺用&a没错过呀~~~


simon21ic 发表于 2008-5-16 13:26 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

26楼: to 24楼:确实,所以这些讨论没有意义


&a+1,这种写法就更本不推荐在程序中使用(或者使用的话,加上强制类型转换),并不是所有编译器都严格按照标准的,特别是8位的MCU的编译器,需要考虑MCU限制和效率问题等。

偶大概翻译一下:
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a
  string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
  converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
  the array object and is not an lvalue. If the array object has register storage class, the
  behavior is undefined.

3.出了作为sizeof,&,或者用于初始化一个数组的字符串外(?),一个具有'array of type'类型的表达式会转化为'pointer to type',并指向数组的第一个单元,并且不能作为左指。。。。



hotpower 发表于 2008-5-16 13:41 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

28楼: 讨论确实没意思~~~俺坚持&a是取变量a所在地址值别人随便去理解吧



wxj1952 发表于 2008-5-17 11:51 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

31楼: 只有一种规则!


只有一种规则!它实际上是以一种相当优雅的方式把我们这些完全不同的概念联系在一起。


《C与指针》P141:
    首先让我们学习一个概念,它被许多人认为是C语言设计的一个缺陷。但是,这个概念实际上是以一种相当优雅的方式把一些完全不同的概念联系在一起的。

考虑下面的声明:
  int a[5];
   a[1]的类型是整型,那a的类型又是什么?它所表示的又是什么?一个合乎逻辑的答案是它表示整个数组,但事实并非如此。
   
   在C中,在几乎所有使用数组名的表达式中,数组名的值是一个指针常量,也就是数组第一个元素的地址。它的类型取决于数组元素的类型:如果它们是int类型,那么数组名就是“指向int的常量指针”;如果它们是其它类型,那么数组名的类型就是“指向‘其他类型’的常量指针”。
   数组具有一些和指针完全不同的特征。例如,数组具有确定数量的元素,而指针只是一个标量值。编译器用数组名来记住这些属性。只有数组名在表达式中使用时编译器才会为它产生一个指针常量。
   注意这个值是指针常量,而不是指针变量,你不能修改常量的值。你只要稍微回顾一下,就会认为这个限制是合理的:指针常量所指向的是内存中数组的起始位置。如果修改这个指针常量,唯一可行的操作就是把整个数组移动到内存的其他位置。但是,程序完成链接之后,内存中数组的位置是固定的。所以当程序运行时,再想移动数组就为时已晚了。因此,数组名的值是一个指针常量。

    只有在两种场合下,数组名并不用指针常量来表示:
1、当数组名作为sizeof操作符的操作数时:sizeof返回整个数组的长度,而不是指向数组的指针的长度。
2、当数组名作为单目操作符的操作数时:取一个数组名的地址所产生的是一个指向该数组的指针,而不是一个指向某个指针常量值的指针。

个人看法:既然说了“在C中......”那么现今所有的C都符合这个“相当优雅的”规则。如果是“有的C编译器这样,另一些编译器那样,......”那么这本世界流行的《C与指针》还不如我们这场讨论有价值?




hotpower 发表于 2008-5-17 16:04 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

32楼: c提倡指针反对数组,可delphi刚好相反~~~


俺喜欢C++和delphi,讨厌C,所以干什么都先想到"数组"或结构(类)~~~

例如俺这几天发了一帖水文:DSP5402之另类的"数组"访问
是dsp访问外部存储器的问题,它实际是访问的数组.

#define FLASH(x)  (*((volatile unsigned char *) 0x8000 + x))
/*----------------------------------------------------------
另类的"数组"访问,外扩的SST39VF800A从0x8000开始
void FlashObj::ChipErase(void)
{
  FLASH(0x5555) = 0xaa;  
  FLASH(0x2AAA) = 0x55;  
  FLASH(0x5555) = 0x80;
  FLASH(0x5555) = 0xaa;  
  FLASH(0x2AAA) = 0x55;  
  FLASH(0x5555) = 0x10;
  Wait(0x5555);
}
void FlashObj::Wait(unsigned int address)
{
unsigned int temp, val;
  do {
    val = FLASH(address);
    __nop();
    temp = FLASH(address);
    __nop();
  }
  while(((val ^ temp) & (1 << BIT6)) != 0);
}
----------------------------------------------------------*/
点击看大图

再有个真数组的水文: DSP281X变量地址数组定位方法

细心的人会看出来:

优秀的编译器对指针/数组/结构成员变量/结构指针的成员变量
等访问最终的优化代码几乎是相同的.

00说的:在keil51上 a==&a   

俺认为可能纯属巧合~~~

如果:
xdata unsigned i;

若此时i==&i俺真的再不玩51了~~~   

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条