记录一下学习C语言,针对自身模糊的地方记录,如有错误,欢迎指正
数组名即为数组首元素的地址,常常与指针联系在一起
10.1 数组
10.1.1 初始化
int powers[8] = {1,2,4,6,8,16,32,64};
const初始化:一旦声明为const后续就不能再赋值了。
const int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};
int a[5] = { 0,1,2 };
printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4], a[5]);//没有初始化的输出为0
int b[5] ;
printf("%d %d %d %d %d", b[0], b[1], b[2], b[3], b[4], b[5]);//输出的是垃圾值
另外,以下图方式也可以对数组进行初始化,[4]=100代表将数组第5个元素赋值为100,后面的[0]=10会将之前的值覆盖。
int a[5] = { 0,1,[4]=100,[0]=10 };
还有一点需要注意,
int a[5] = { 0,1,2,3,4 };
printf("%d %d", a, a + 1);
10.1.2 函数中调用数组
数组名为首地址,首地址+1,代表向后移动一个int类型,4个字节,32位,对于不同类型的数组,地址偏移不同,如double为8个字节,64位。
*(a+1)即为a[1],值得注意的是间接运算符*的优先级高于+,所以与*a+1代表含义不同。
在函数中对数组进行调用,一般通过调用首地址,也就是数组名,以及数组元素个数(也可以将函数的参数定义为,数组的首地址与尾地址)。
int sum(int *a, int n);
int sum(int a[], int n);
int sum(int*, int);
int sum(int[], int);
以上四种函数声明等价,但是在函数定义中不能省略参数名,否则在函数内无法调用。
指针也可以进行自增、自减的操作,同时两个指针相减代表的含义为中间差多少个字节,
如int a[5]; a[2]-a[0]=2,代表中间隔了两个元素,两个int型。
注意事项:千万不能解引用未初始化的指针。
int *pt;
*pt = 5;
因为pt未被初始化,是一个随机值,所以这个5不知道会被存储到哪里,有可能会出现问题。创建一个指针的时候系统只分配了储存指针本身的内存,没有存储数据的内存,所以在使用指针前,必须用已分配的地址初始化它,或者可以用malloc()函数先分配内存。
10.1.3 关于const
int rate[5]={1,2,3,4,5};
const int *p=rate;
//将p指向的int类型的值声明为const,表示不能使用p来改变它所指向的值
*p=10;//不允许
p[1]=10;//不允许
rate[0]=10;//允许,因为rate没被const
p++;//可以,因为const的是p所指向的值,而不是地址。
同时,不能将const数据的地址赋值给别的指针,否则这样就可以通过这个指针去修改const数据。
注意下图与之前的形式的不同:之前限定的是int类型的值,下图限定的是指针p
int * const p=rate;
p=&rate[2];//不允许,该指针不能指向别处
*p=10; //可以
10.2 多维数组
初始化没什么好说的,与一维数组类似,需要注意的是书写形式
int b[2][3] = {
{1,2,3},
{4,5,6}
};
二维数组的数组名b是首元素的地址,b的首元素是一个内含3个int的数组,b[0]代表第0行,只占用一个int大小的地址。b+1代表第1行,而b[0]+1代表第0行的元素的第1列也就是,其值为2。正因为如此地址b与地址b[0]与&b[0]三者代表的地址一样,但是其中代表的含义需要辨别。
b:第0行,b+1代表第一行,*b+1代表b[0][1]的地址,而*(b+1)又代表什么呢,第一行的首地址,可以通过*(b+1)+1得到b[1][1]的地址。*(b+1)+1, b[1] + 1两者地址相同。可以理解为一个*进入列的操作,两个*得到值。
b[0]:第0行,与第一个的区别就是它可以通过+1转到下一个元素,而不是直接跳一行;
10.3 指向多维数组的指针
int (*p) [3];//p指向一个内含3个int 的类型值的数组
int * q [3];//q是一个内含3个指针元素的数组,每个元素都指向int的指针,
//因为[]的优先级高,*表示数组q内含有两个指针
p=b;
printf("%d %d %d ", *(p + 1) + 1, p[1] + 1, p + 1);
printf("%d %d %d\n", *(b+1)+1, b[1] + 1, b + 1);
可以看到,可以通过p来调用二维数组b;
指针之间不同类型不能赋值,另外指针也有自己的地址。
int a = 10;
int *b=&a;
printf("%d %d %d", b, &b ,*b);
可以看到存储数据的地址和存储指针的地址是不一样的。