数组,指针,数组指针
2012-10-31 09:35
309 查看
先看下下面这个例子:
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返回整个数组所占用的字节而不是一个指针所占用的字节。单目操作符&返回一个指向数组的指针,而不是一个指向数组第一个元素的指针的指针。
指针和数组并不相等。数组的属性和指针的属性大相径庭。当我们声明一个数组时,它同时也为数组分配了一些内存空间,用于容纳数组元素。但是,当我们声明一个指针时,它只分配了用于容纳指针本身的空间。
当数组名作为函数参数传递时,实际传递给函数的是一个指向数组第一个元素的指针。函数所接受到的参数实际上是原参数的一份拷贝,所以函数可以对其进行操纵而不会影响实际的参数。但是,对指针参数执行间接访问操作允许函数修改原先的数组元素。数组形参既可以声明为数组,也可以声明为指针。这两种声明形式只有当它们作为函数的形参时才是相等的。
多维数组实际上是一维数组的一种特例,就是它的每个元素本身也是一个数组。多维数组中的元素根据行主序进行存贮,也就是最右边的下标率先变化。多维数组名的值是一个指向它第一个元素的指针,也就是一个指向数组的指针。对该指针进行运算将根据它所指向数组的长度对操作数进行调整。多维数组的下标引用也是指针表达式。当一个多维数组名作为参数传递给一个函数时,他所对应的函数形参的声明中必须显示指明除第一维外所有的维的长度。由于多维数组实际上是复杂元素的一维数组,一个多维数组的初始化列表就包含了这些复杂元素的值。这些值的每一个都可能包含嵌套的初始值列表。由数组各维的长度决定。如果多维数组的初始化列表是完整的,它的内层花括号可以省略。在多维数组初始化列表中,只有第一维的长度会被自动计算出来。
指针数组与数组指针
我说的很直白,简单易懂,给在迷茫的孩子和自己总结与复习。
这是我在华清培训的时候老师讲的一道题,老师讲的我想哭,后来自己想了想
下面这个是一个比较经典的例子
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
输出:2,5
*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5
重要的来了哈
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小
int *ptr=(int *)(&a+1);
则ptr实际是&(a[5]),也就是a+5
原因如下:
&a是数组指针,其类型为 int (*)[5];
而指针加1要根据指针类型加上一定的值,
不同类型的指针+1之后增加的大小不同
a是长度为5的int数组指针,所以要加 5*sizeof(int)
所以ptr实际是a[5]
但是prt与(&a+1)类型是不一样的(这点很重要)
所以prt-1只会减去sizeof(int*)
a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].
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返回整个数组所占用的字节而不是一个指针所占用的字节。单目操作符&返回一个指向数组的指针,而不是一个指向数组第一个元素的指针的指针。
指针和数组并不相等。数组的属性和指针的属性大相径庭。当我们声明一个数组时,它同时也为数组分配了一些内存空间,用于容纳数组元素。但是,当我们声明一个指针时,它只分配了用于容纳指针本身的空间。
当数组名作为函数参数传递时,实际传递给函数的是一个指向数组第一个元素的指针。函数所接受到的参数实际上是原参数的一份拷贝,所以函数可以对其进行操纵而不会影响实际的参数。但是,对指针参数执行间接访问操作允许函数修改原先的数组元素。数组形参既可以声明为数组,也可以声明为指针。这两种声明形式只有当它们作为函数的形参时才是相等的。
多维数组实际上是一维数组的一种特例,就是它的每个元素本身也是一个数组。多维数组中的元素根据行主序进行存贮,也就是最右边的下标率先变化。多维数组名的值是一个指向它第一个元素的指针,也就是一个指向数组的指针。对该指针进行运算将根据它所指向数组的长度对操作数进行调整。多维数组的下标引用也是指针表达式。当一个多维数组名作为参数传递给一个函数时,他所对应的函数形参的声明中必须显示指明除第一维外所有的维的长度。由于多维数组实际上是复杂元素的一维数组,一个多维数组的初始化列表就包含了这些复杂元素的值。这些值的每一个都可能包含嵌套的初始值列表。由数组各维的长度决定。如果多维数组的初始化列表是完整的,它的内层花括号可以省略。在多维数组初始化列表中,只有第一维的长度会被自动计算出来。
指针数组与数组指针
我说的很直白,简单易懂,给在迷茫的孩子和自己总结与复习。
这是我在华清培训的时候老师讲的一道题,老师讲的我想哭,后来自己想了想
下面这个是一个比较经典的例子
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
输出:2,5
*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5
重要的来了哈
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小
int *ptr=(int *)(&a+1);
则ptr实际是&(a[5]),也就是a+5
原因如下:
&a是数组指针,其类型为 int (*)[5];
而指针加1要根据指针类型加上一定的值,
不同类型的指针+1之后增加的大小不同
a是长度为5的int数组指针,所以要加 5*sizeof(int)
所以ptr实际是a[5]
但是prt与(&a+1)类型是不一样的(这点很重要)
所以prt-1只会减去sizeof(int*)
a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].
相关文章推荐
- 关于LinuxC/C++中字符指针char * str 与字符数组 char str []的一点小区别
- 数组、指针和内存管理
- C语言字符串数组与字符串指针详解
- C++ new一个数组时,指针移动程序崩溃问题
- 黑马程序员—C语言指针与数组
- 数组名和指针的区别
- C语言中的指针和数组
- 关于动态数组指针操作的两个例子
- 字符、地址详解(及字符串指针、字符数组关系)
- 冒泡法排序的两种方法—指针和数组
- 编写安全代码:数组和指针的本质以及何时不能互换
- 字符数组和字符串指针
- C专家编程 十三 数组和指针参数是如何被编译器修改的
- 黑马程序员——指针、指针与数组、指针与字符串
- 数组与指针
- 数组与指针
- C语言指针回顾(四) 指针与数组之间的关系
- this指针以及类的数组
- 字符数组与字符指针
- 《C专家编程》数组和指针并不同--多维数组