linux c 一站式学习 C语言中数组名和指针的区别

来源:互联网 发布:dns 多域名 同一ip 编辑:程序博客网 时间:2024/06/05 19:16

首先解释两个概念 常量指针 指针常量

常量指针定义 const  类型*  

指向的对象是常量的指针  const int *pi:*pi是不可以改变的,  *pi=2之类的对于*pi的操作都是不可取的
可以改变pi指向的地址,即可以改变指针指向的地址,但是不可以改变它指向的地址里面存的内容
 指针常量定义  类型*const  
指针本身是常量   int * const pi:*pi是可以改变的,  pi=&i这种操作是不正确的
即可以改变这个指针指向的地址里面存的内容,但是不可以改变这个指针指向的地址
正题
#include <stdio.h>    int a[2] = {1,2};  int main(){          printf("a = %p\n", a); // I          printf("&a = %p\n", &a); // II          printf("a + 1 = %p\n", a + 1);// III          printf("&a + 1 = %p\n", &a + 1);// IV            return 0;  }  
本机(linux)结果输出:
a = 0x804a014
&a = 0x804a014
a + 1 = 0x804a018
&a + 1 = 0x804a01c
没错,上面I 和 II打印出来的地址是一样的,IV 要比 III 大4个字节的地址空间。下面是我对这一现象的解释,如有不妥的地方请各位大虾一定给于指出:
首先引用《C和指针》p141中的理论: 在C中, 在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址。 它的类型取决于数组元素的类型: 如果它们是int类型,那么数组名的类型就是“指向int的常量指针“。 看到这里我想应该就知道为什么 会有I 和 III式的结果了。
对于II 和 IV 则是特殊情况,在《C和指针》p142中说到,在以下两中场合下,数组名并不是用指针常量来表示,就是当数组名作为sizeof操作符和单目操作符&的操作数时。 sizeof返回整个数组的长度,而不是指向数组的指针的长度。 取一个数组名的地址所产生的是一个指向数组的指针,而不是一个指向某个指针常量的指针。 所以&a后返回的指针便是指向数组的指针,跟a(一个指向a[0]的指针)在指针的类型上是有区别的。
还有一种情况
#include <iostream>  void arrayTest(char str[])  {    cout << sizeof(str) << endl;  }  int main()  {    char str1[10] = "I Love U";    arrayTest(str1);   return 0; }
程序的输出结果为4。不可能吧? 一个可怕的数字,前面已经提到其为指针的长度! 
数组名内涵为数组这种数据结构,在arrayTest函数体内,str是数组名,那为什么sizeof的结果却是指针的长度?
 这是因为: 
(1) 数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针; 
(2) 很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。 
所以,数组名作为函数形参时,其全面沦落为一个普通指针!它的贵族身份被剥夺,成了一个地地道道的只拥有4个字节的平民。

总结:编译器通过用户是否给出&,来决定指针变量的类型,进而翻译为相应的汇编码。 或者换句话说,&符只是用来表明变量a取地址后得到的值,被看作什么类型的指针,而不是用来表示对a进行取地址操作。
http://www.cnblogs.com/furaibo/archive/2010/03/19/1689710.html
http://www.cnblogs.com/hdu-2010/p/3557784.html
拓展:字符串字面值做右值,自动变换为指针
 
原创粉丝点击