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

《C专家编程》里面关于数组和指针的一个小疑点

2012-02-15 
《C专家编程》里面关于数组和指针的一个小问题书中说了,定义一个数组,比如chara[100],如果在别的地方声明,则

《C专家编程》里面关于数组和指针的一个小问题
书中说了,定义一个数组,比如char   a[100],如果在别的地方声明,则应该使用extern   char   a[],而不应该使用extern   char   *a这样的语句,因为编译器对指针和数组的处理有差别,extern   char   *a会引起错误或潜在的问题。

首先书中说了对于数组a和指针p,a[i]和p[i]机制的不同:

a[i]的存取步骤是:
    步骤1:取得a所代表的值(就是数组首地址,比如说是9980);
    步骤2:取i的值,将它与9980相加;
    步骤3:取地址9980+i处的内容。

但是*p的存取步骤则是:
    步骤1:符号表中p的值(也就是指向的地址,比如说是4624);    
    步骤2:取地址4624的内容,比如是“5081”;
    步骤3:取地址5081处的内容。

书中还说了,如果书写了extern   char   *p,然后用p[3]来引用其中的元素时,其操作机制实质是上述两种方法的组合。更正式的说法,编译器会:1、取得符号表中p的地址,提取存储在此处的指针;2、把下标表示的偏移量与指针的值相加,产生一个新的地址;3、访问这个地址,取值。既然用extern语句把p声明为指针,那么不管p原先定义的是指针还是数组,用p[i]的方式访问数据,都会按这三个步骤进行。如果原先定义的是char   p[10]这种情形,那么p[3]的本意是得到一个字符,然而按照上面的方法,编译器却把其当成一个指针,把ASCII字符解释为指针显然是牛肉不对马嘴。

我现在非常纳闷,按这三个步骤,编译器怎么会把p[3]误解为指针呢,首先在符号表中取数组p的值,也就是数组开始的首地址,然后与偏移量相加得到新的地址,再取值,好像顺理成章的,没看出哪里有问题呀,请高人指点。

[解决办法]
数组和指针还是有那么一点点的区别,
所以 extern char a[] 比较合适 ...
[解决办法]
差别在于数组只取了一次,指针取了两次
[解决办法]
lz所说属实!

[解决办法]
指针与数组名的差别仅仅在于作为函数 参数 时才体现出来。其他时候一模一样!

上面打误了。
[解决办法]
我也困惑于这个问题,昨天晚上看书也看到这里,不是很明白,也许是翻译的问题,希望高手指点。
[解决办法]
不好意思,刚才没理解清楚楼主的意思,就随便回了篇帖子
后来又找了书看,想了想,这个问题其实也不难理解
试了下:
#define#
char p[] = { 'a ', 'b ', 'c ', 'd ', 'e '};

#declaration#
#include <stdio.h>
<>
int main(void)
{
< > extern char *p;
< > printf( "%x\n ", &p);
< > print(&p);
< > print(P);
< > return 0;
}
<>
int print(char *p)
{
< > printf( "%X\n ", p);
< > printf( "%X\n ", *p);

< > return 0;
}

1) 若声明为 extern char p[]时,p的值为0x402000,p[i](0x402000+i)索引无误
2) 若声明为 extern char *p时,p的值为0x64636261,p[i](0x64636261+i)索引出错
此时&p为0x402000
0x64636261恰好为0x402000指向的 'd ' 'c ' 'b ' 'a ',然后编译器用这些ascii值组合成一个*实际上*是错误的地址,再根据这个错误的地址进行索引,最终导致了出错

至于为什么会出现这样的错误,这应该就是书中所要表达的内容
[解决办法]
to hsw_c(寒冰)

一样的。 *(p+3)
1。首先取p的符号 假设是6045
2。到6045区读内容 假设是500000
3。偏移3*sizeof(*p) 即3*1 得到500003
4。取出500003中的内容。
[解决办法]
halve(Rangers,lead the way!) 说的对
[解决办法]
首先对楼主的一些说法做一下更正,以免引起歧义

但是*p的存取步骤则是:
步骤1:符号表中p的地址(也就是指针自身的地址,比如说是4624);
步骤2:取地址4624的内容,比如是“5081”(也就是指针指向的地址);
步骤3:取地址5081处的内容。

=======================================================
从这里我们可以看出,对于一个指针来说,有两个地址,一个是指针自身的地址,另外一个则是指针所指向的地址,换句话来将,就是指针的值。

在楼主的这个例子里,问题出在 extern char *a/a[]的初始化上面
1.对于extern char a[]; 这里a 被当作一个数组,其初始化的值就是数组的地址。
2.对于extern char *a; 这里a 被当作一个指针,那它初始化的值是哪一个?应该是指针指向的地址(也就是指针的值),换句话来讲,就是把数组a当作一个指针,从其起始地址起,后面32位所存储的内容就是 "指针指向的地址 "。就楼主的具体例子来讲,就是 'd ' 'c ' 'b ' 'a '四个字节组成指针的值,即0x64636261

------解决方案--------------------


这样理解吧:书中讲了a[i]和*p的存取步骤不相同。而

p[i]和*(p+i)是同样的步骤:*p和a[i]步骤之和,是指针和数组的存取步骤相加,此时
extern char *p;即p为指针。

对不?请指点,谢谢!
[解决办法]
书中说了,定义一个数组,比如char a[100],如果在别的地方声明,则应该使用extern char a[],而不应该使用extern char *a这样的语句,因为编译器对指针和数组的处理有差别,extern char *a会引起错误或潜在的问题。

------------------------------------------
编译器直接报错:

redefinition; different types of indirection

热点排行