数组名作为左值和右值的区别
数组名作为右值时,表示的是数组的首地址,而不是数组首元素的地址。
数组名不能作为左值。因为数组名相当于一个指针常量(指针类型的常量)。这是数组名和一般的指针变量最大的区别。
对一个指针加减一个整型常量表示的是偏移N个元素占用内存空间后的地址。
有关数组全局变量的定义和声明
定义: extern char a[100];
声明: extern char a[ ]; 注意这里并不需要指明数组的长度。
------------
编译器会把存储在指针变量中的任何数据当作地址来处理。
在上面如果对a数组进行声明时使得了extern char* a; 而数组a中存储的值为”abcdefg”
则编译器会将abcd当作一个地址,并用这个地址间接寻址。对于数组a第四个字节后面的值,则无法通过声明的指针来访问。
--------------
数组指针完全可以这样定义
int (*)[10] p2; 但一般是int (*p2)[10];
对一个指针使用下标运算符时,如果下标中的数值是负数,表示将当前地址“减”一个类型的长度。
--------------------------下面这些一直理解不了,就当作范例记住吧!!!-------------------
char a[3][4];
a)对于二维数组,编译器总是将其看作一个一维数组,而其中的每个元素又都是一个一维数组。
b)a[3]这个一维数组的3个元素分别是:a[0]/a[1]/a[2],每个元素的大小都是sizeof(a[0]),即sizeof(char)*4;
c)a[0]/a[2]/a[2]这三个元素的首地址分别为&a[0]、&a[0]+1*sizeof(char)*4、&a[0]+2*sizeof(char)*4,即a[i]的首地址为&a[0]+i*sizeof(char)*4.
//不同于一维数组,这里的&a[0]表示的是值为a[0]的地址的char*类型的指针。
d)考虑a[i]里面的内容:
a[i]内的4个元素的首(字节,这里是char类型,单字节,所以可直接称为首地址)地址分别为:&a[i],&a[i]+1*sizeof(char),&a[i]+2*sizeof(char),],&a[i]+3*sizeof(char),即a[i][j]的首地址为&a[i]+j*sizeof(char);
如果把a[i]用a表示,得到a[i][j]的地址可表示为:
a+i*sizeof(char)*4+j*sizeof(char); 以指针表示则为 *(*(a+i)+j)
分析:a单独用实际上是一个 char (*)[4]; a+i表示从a向后偏移4个数组的长度后的地址,仍为一个数组指针。对数组指针解引用*(a+i),获取到的是这个一维数组首元素的地址,相当于一维数组中的array,而不是&array,此时的类型为char* ;*(a+i)+j表示向后偏移j*sizeof(char)个字节的地址。再解引用得到a[i][j]. 在a+i这步虽然a是一个指针常量,但是a+i并没有对a进行赋值,只是引用,并不违反相关语法。
注意:
1.如果在一个一维数组a中,*a,a[0],*&a,*(&a)的值是否相同?