首先,看两个指针和数组使用的例子:
1.a,b,c三行的输出会有什么不同?
int ar[10];
void func(int ar[10])
{
printf("%x %x %x ",&ar,&ar[0],sizeof ar);// a
}
void func2(int *pr)
{
printf("%x %x %x ",&pr,&pr[0],sizeof pr);// b
}
void main(void)
{
printf("%x %x %x ",&ar,&ar[0],sizeof ar);// c
func(ar);
func2(ar);
}
2.在文件1中定义全局数组,
int muss[4]={0,1,2,3};
在文件2中声明,
extern int *muss;
muss[0]的值会是什么?
这两个例子有点钻牛角尖,不过它们很直接的表明了一件事情,指针和数组在有些时候是一样的,而在另一些时候不一样。问题是,什么时候会不一样?
通过指针和数组访问数据
定义了一个数组和一个指针,
char a[5]="abcd";
char *b=a;
在运行时,程序访问a[1]和b[1]的过程并不一样。在内存中,从a表示的地址开始,存放的内容依次是'a','b','c','d'。所以访问a[1]的方式就是把a的地址加上偏移量1,取出对应地址的内容。
在b表示的地址,存放的内容则是a的地址数值。访问b[1]的方式就变为,取出b对应地址的内容,把它作为地址再加上偏移量1,取出对应地址的内容。
回过头来,我们看看在例子2中发生事情。muss在文件2中被声明为
extern int *muss;
而它的定义却是
int muss[4]={0,1,2,3};
当在文件2中访问muss[0]时,编译器把muss表示的地址中存放的内容 0 当作指针值,准备去访问地址0的内容,错误自然就发生了。
作为指针处理的数组
在C标准中有如下规则,
1.表达式中的数组,编译器当作一个指向该数组第一个元素的指针处理;
(C99 6.3.2.1)
2.数组下标等价于指针的偏移量;也就是说a[7]或7[a],等价于*(a+7);
(C99 6.5.2.1)
3.用作函数的形参时,数组被编译器当作一个指向该数组第一个元素的指针处理;
(C99 6.9.1)
对于规则1,C标准规定了三种例外情况:
第一,作为sizeof的操作数时,这时得到的结果是数组占用空间的总数。
第二,作为单目运算符&的操作数时,指针作操作数将得到其本身地址,而数组名作操作数将得到数组第一个元素的地址。
第三,用作初始值的字符串常量数组。
现在,我们来看看例子1的结果,三项输出,只有第二项是不变的。两个被调用函数形参的类型实际都是指向int的指针,第一项输出的其实是这个指针的地址,而第三项输出的则是指针的大小。(如果想要进一步验证,可以对func函数中的ar赋值,看看结果。数组名不是可赋值的左值,是不能被赋值的。)
SUMMARY
数组和指针的关系可以简述如下:
1.指针就是指针,它决不会被编译器改成数组。在程序中可以使用指针和下标的组合方式,比如p[7],这是因为p[7]总是会编译器解释为*(p+7)。
2.只有在一种情况下,即作为函数的形参时,声明为数组与声明为指针是等价的。这时,无论选择哪一种声明形式,在函数内部都被解释为指针。
3.在其他所有情况下,声明的形式必须与定义的形式一致。定义为数组,extern声明为数组,定义为指针,extern声明为指针。
[@more@]
1.a,b,c三行的输出会有什么不同?
int ar[10];
void func(int ar[10])
{
printf("%x %x %x ",&ar,&ar[0],sizeof ar);// a
}
void func2(int *pr)
{
printf("%x %x %x ",&pr,&pr[0],sizeof pr);// b
}
void main(void)
{
printf("%x %x %x ",&ar,&ar[0],sizeof ar);// c
func(ar);
func2(ar);
}
2.在文件1中定义全局数组,
int muss[4]={0,1,2,3};
在文件2中声明,
extern int *muss;
muss[0]的值会是什么?
这两个例子有点钻牛角尖,不过它们很直接的表明了一件事情,指针和数组在有些时候是一样的,而在另一些时候不一样。问题是,什么时候会不一样?
通过指针和数组访问数据
定义了一个数组和一个指针,
char a[5]="abcd";
char *b=a;
在运行时,程序访问a[1]和b[1]的过程并不一样。在内存中,从a表示的地址开始,存放的内容依次是'a','b','c','d'。所以访问a[1]的方式就是把a的地址加上偏移量1,取出对应地址的内容。
在b表示的地址,存放的内容则是a的地址数值。访问b[1]的方式就变为,取出b对应地址的内容,把它作为地址再加上偏移量1,取出对应地址的内容。
回过头来,我们看看在例子2中发生事情。muss在文件2中被声明为
extern int *muss;
而它的定义却是
int muss[4]={0,1,2,3};
当在文件2中访问muss[0]时,编译器把muss表示的地址中存放的内容 0 当作指针值,准备去访问地址0的内容,错误自然就发生了。
作为指针处理的数组
在C标准中有如下规则,
1.表达式中的数组,编译器当作一个指向该数组第一个元素的指针处理;
(C99 6.3.2.1)
2.数组下标等价于指针的偏移量;也就是说a[7]或7[a],等价于*(a+7);
(C99 6.5.2.1)
3.用作函数的形参时,数组被编译器当作一个指向该数组第一个元素的指针处理;
(C99 6.9.1)
对于规则1,C标准规定了三种例外情况:
第一,作为sizeof的操作数时,这时得到的结果是数组占用空间的总数。
第二,作为单目运算符&的操作数时,指针作操作数将得到其本身地址,而数组名作操作数将得到数组第一个元素的地址。
第三,用作初始值的字符串常量数组。
现在,我们来看看例子1的结果,三项输出,只有第二项是不变的。两个被调用函数形参的类型实际都是指向int的指针,第一项输出的其实是这个指针的地址,而第三项输出的则是指针的大小。(如果想要进一步验证,可以对func函数中的ar赋值,看看结果。数组名不是可赋值的左值,是不能被赋值的。)
SUMMARY
数组和指针的关系可以简述如下:
1.指针就是指针,它决不会被编译器改成数组。在程序中可以使用指针和下标的组合方式,比如p[7],这是因为p[7]总是会编译器解释为*(p+7)。
2.只有在一种情况下,即作为函数的形参时,声明为数组与声明为指针是等价的。这时,无论选择哪一种声明形式,在函数内部都被解释为指针。
3.在其他所有情况下,声明的形式必须与定义的形式一致。定义为数组,extern声明为数组,定义为指针,extern声明为指针。
[@more@]
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9650775/viewspace-923210/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/9650775/viewspace-923210/