C和指针 第八章数组
本文系读后感,以防自己以后忘记之用
1.数组名是一个指针常量,也就是数组的第一个元素的地址,数组名只有两种情况并不用指针常量来表示–就是当数组名作为sizeof操作符或单目操作符的操作数是,sizeof返回整个数组的字节数。
2.负值下标,不要感到不可思议,因为下标引用是间接访问表达式,你需要把算出它的地址[由数组名和相关的信息得到],但是这是一个很不好的习惯.
3.下标绝不会比指针更有效率,但是指针有可能比下表有效率.[循环时每次步长是一样的时候],但是下标的可读性更好,不要为了效率上的细微差别而牺牲可读性.
4.数组的初始化,可以用大括号防止很难阅读的情况,比如说一个三维数组,只有两个数初始化不是0,那么你用{{{},{}},{{},{}}} 这样的更好一些,层次分明,而且可以少些很多0.C的数组是行主序,下面的定义是可以通过编译的,但是不是你想要的结果matrix[4,3],这里不是一个二维数组,二是一个一维数组;下标引用的优先级高于间接访问,所以指向数组的指针写成int (p)[];int p[],是指针数组,数组名作为参数传到函数中去的话,只有第一维的大小可以省略,后面维数的大小不能省,所以原型不能写成func(int *matrix)这样的,这里第二维没有给出大小.
下面是两个练习题:
1.下面的声明取自某个源文件
int a[10];
int b=a;
但在另一个不同的源文件中,却发现了这样的代码:
extern int *a;
extern int b[];
x=a[3];
y=b[3];
上面两个赋值都是错误的,解释如下
第一个赋值中,编译器认为a是一个指针变量,所以它提取存储在那里的指针指,并加上12(3和整型的长度相乘),然后对这个结果执行间接操作.但a实际上是整形数组的起始位置,所以作为”指针”获得的这个值实际上是数组的第一个整形元素,加上12后,结果解释为一个地址,然后对它进行间接访问.作为结果,它或者将提取一些任意内存位置的内容,或者由于某种地址错误而导致程序失败
第二个赋值中,编译器认为b是一个数组名,所以它把12(3的调整结果)加到b的存储地址,然后间接访问操作从那里获得值.事实上,b是个指针变量,所以从内存中提取的后面三个字实际上是从另外的任意变量中取得的.这个问题说明指针和数组虽然存在关联,但绝不是相同的.
2.void func(int const a,int const b[]){}中两个const的区别.
首先a是一个拷贝值,所以加不加const都不会改变原变量的值,如果b作为一个变量也是不会改变原变量的值,但是b可以通过间接访问改变其他位置的值,所以加上const之后,间接访问到的值也不可以改变