1.const 关键字声明后数据不能修改
2.sizeof 数组名指的是整个数组的大小(以字节为单位)
sizeof 数组名[0]指的是数组中一个元素的大小
整个数组的大小除以单个元素的大小就是数组元素的个数
3.初始化器的重要性
1)如果初始化器后面有更多的值。那么后面的值将被用于初始化指定元素后面的元素
2)如果再次初始化指定的元素,那么最后的初始化将会取代之前的初始化
4.C不允许把数组作为一个单元赋给另一个数组,初初始化以外也不允许使用花括号列表的形式赋值
#define SIZE 5
int main(void)
{
int oxen[SIZE] = {0,1,2,3}; /*初始化没问题,不足的参数设置为0*/
int yaks[SIZE];
yaks = oxen; /*不允许*/
yaks[SIZE] = oxen[SIZE];/*数组下标越界*/
yaks[SIZE] = {0,1,2,3};/*不起作用*/
}
5.数组边界
在C标准中,使用越界下标的结果是未定义的
使用越界的数组下标可能会导致程序改变其他变量的值。不同的编译器运行同一个程序的结果可能不同,有些会导致程序异常中止。
要注意数组的边界
6.指针和数组
short类型占两个字节、double类型占八个字节
在C中,指针加一指的是增加一个存储单元,对数组而言,这意味着加一后得到地址是下一个元素的地址,而不是下一个字节的地址,所以必须声明指针所指向对象的类型
系统中地址是按字节编码的
7.total += *start++;//一元运算符*和++的优先级相同,但结合律是从右往左
即表示为:1)*start++=*(start++) => m=start;*m;start++(先把指针指向位置上值取出,然后再递增指针)
2)total = total+*m;
8.int * p = & a;//p是指向a的指针,p中存的是a的地址
&p 是指向指针p的指针,&p中存的是指针p的地址
9.创建一个指针时,系统只分配了储存指针本身的内存,并未分配存储数据的内存,因此,在使用指针之前,必须先用已分配的地址初始化它。
10.const 指针是指不能用指针来改变它所指向的值,但是可以让指针指向别处
11.1)把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的
double rate[5] ={1,2,3,4,5};
const double locked[4]={1,2,3,4};
const double *pc = rate; //有效
pc = locked;//有效
pc = &locked[3] ;//有效
2)只能把非const数据的地址赋给普通指针
double rate[5] ={1,2,3,4,5};
const double locked[4]={1,2,3,4};
double *pp = rate;//有效
pp = locked;//无效<因为如果成立的话就可以用指针改变locked的值了>
pp = &rate[3];//有效
12.double * const pc = &rate;//可以初始化一个不能指向别处的指针
13.int (* p)[2];//p指向一个内含两个int类型值的数组
int * p[2];//p是一个内含两个指针元素的数组,每个元素都指向int 的指针
14.指针的兼容性
指针之间的赋值比数值类型之间的赋值要严格
假如有如下声明:
int * pt;
int (*pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2;//一个指向指针的指针
有如下语句:
pt = &ar1[0][0];//都是指向int的指针
pt = ar1[0];//都是指向int的指针
pt = ar1;//无效
pa = ar1;//都是指向内含3个int类型元素的数组的指针
pa = ar2;//无效
p2 = &pt;//both point-to-int *
*p2 = ar2[0];//都是指向int的指针
p2 = ar2;//无效
15.把const指针赋给非const指针不安全,因为这样可以使用新的指针改变const指针指向的数据
但是把非const指针赋给const指针没问题,前提是只进行一级解引用
16.编译器会把数组表示法转换成指针表示法
ar[1] -> ar+1;
int ar[][length] ->表示ar指向一个内含length个int类型值的数组
int sum2(int ar[3][4],int rows);//有效声明,但是3会被忽略
17. 在把数组名作为实际参数时,传递给函数的不是整个数组,而是数组的地址(因此,函数对应的形式参数是指针)
网友评论