现在的位置: 首页 > 综合 > 正文

数组,指针,数组指针

2014年01月25日 ⁄ 综合 ⁄ 共 1766字 ⁄ 字号 评论关闭

先看下下面这个例子:

  Inta[5]; 定义一个数组,其包含了5个int型的数据,我们可以用a[0],a[1]等来访问数组里面的每一个元素。这里的a[0],a[1]等为a的元素,但并非元素的名字。数组的每一个元素都是没有名字的。

  Sizeof(a)的值为sizeof(int)*5,32位系统下为20,数组的长度。

  Sizeof(a[0])的值为sizeof(int),32位系统下为4,数组单个元素的长度。

Sizeof(&a[0])的值在32位系统下是4,这个很好理解。取元素a[0]的首地址。

Sizeof(&a)的值在32位系统下也为4,这也很好理解。取数组a的首地址。

那么&a[0]和&a到底有啥区别呢?a[0]是一个元素,a是整个数组,虽然&a[0]和&a的值一样,但是意义不一样,前者是数组首元素的首个地址,而后者是数组的首地址,举个例子:湖南的省政府在长沙,而长沙的市政府也在长沙。

a作为右值时其意义和&a[0]是一样的,代表的是数组首元素的首地址。而不是数组的首地址

a和&a的区别

main()

{

  int a[5]={1,2,3,4,5};

int *p=(int *)(&a+1);

printf(“%d,%d”,*(a+1),*(p-1));

}

对指针进行加1,得到的是下一个元素的地址,而不是原有地址直接加1。所以,一个类型为T的指针的移动,以sizeof(T)为移动单位。

*(a+1):a和&a的值是一样的,但意思不一样,a是数组首元素的首地址,也就是a[0]的首地址,&a是数组的首地址,a+1是数组下一个元素的首地址,即a[1]的首地址,&a+1是下一个数组的首地址。所以输出为2.

*(p-1):因为p是指向a[5],并且p是int *类型。所以*(p-1)是指向a[4],输出为5

 

int main(void)

{

Char a[5]=”ABCD”;

Char (*p1)[5]=&a;   //&a是整个数组的首地址。他的类型是int  [10];

Char (*p2)[5]=a;     //a是数组的首元素的首地址。他的类型可以理解成 char *;

}

P1和p2都是数组指针,指向的是整个数组。&a是整个数组的首地址。a是数组首元素的首地址。其值相同但是意义不一样。C语言中,赋值符号“=”两边的数据类型必须相同(必须是门当户对),如果不同需要显示或者隐式的类型转换。P1这个定义的”=”号两边的数据类型完全一致,而p2这个定义的”=”号两边的数据类型就不一致了。左边的类型是指向整个数组的指针,右边的数据类型是指向单个字符串的指针。

在绝大多数表达式中,数组名的值是指向数组第一个元素的指针。这个规则只有两个例外。sizeof返回整个数组所占用的字节而不是一个指针所占用的字节。单目操作符&返回一个指向数组的指针,而不是一个指向数组第一个元素的指针的指针。

指针和数组并不相等。数组的属性和指针的属性大相径庭。当我们声明一个数组时,它同时也为数组分配了一些内存空间,用于容纳数组元素。但是,当我们声明一个指针时,它只分配了用于容纳指针本身的空间。

 

当数组名作为函数参数传递时,实际传递给函数的是一个指向数组第一个元素的指针。函数所接受到的参数实际上是原参数的一份拷贝,所以函数可以对其进行操纵而不会影响实际的参数。但是,对指针参数执行间接访问操作允许函数修改原先的数组元素。数组形参既可以声明为数组,也可以声明为指针。这两种声明形式只有当它们作为函数的形参时才是相等的。

多维数组实际上是一维数组的一种特例,就是它的每个元素本身也是一个数组。多维数组中的元素根据行主序进行存贮,也就是最右边的下标率先变化。多维数组名的值是一个指向它第一个元素的指针,也就是一个指向数组的指针。对该指针进行运算将根据它所指向数组的长度对操作数进行调整。多维数组的下标引用也是指针表达式。当一个多维数组名作为参数传递给一个函数时,他所对应的函数形参的声明中必须显示指明除第一维外所有的维的长度。由于多维数组实际上是复杂元素的一维数组,一个多维数组的初始化列表就包含了这些复杂元素的值。这些值的每一个都可能包含嵌套的初始值列表。由数组各维的长度决定。如果多维数组的初始化列表是完整的,它的内层花括号可以省略。在多维数组初始化列表中,只有第一维的长度会被自动计算出来。

抱歉!评论已关闭.