一.数组
1.定义:int arr[n]; //n为元素个数
2.数组的三种初始化方法:
①完全初始化:arr[10] = {0,1,2,3,4,5,6,7,8,9};
②不完全初始化:arr[10] = {0,1,2,3};
注:在不完全初始化中 至少赋1个的值 其余没有进行赋值的数为0
③int arr[] = {0,1,2,3};
3.数组的遍历:for循环输出arr[下标数字]
4.一般情况下 数组的名字→首元素的地址
*arr = 100会使数组的第一个值改变 但是当数组名与&和sizeof()结合使用的时候 代表的是整个数组
例如:
1 printf("%d ",sizeof(arr)); 2 printf("%d ",sizeof(int [10]));
以上两种输出方式的结果都是40
1 printf("%d ",arr); 2 printf("%d ",arr+1);
这两种输出方式的结果相差4
1 printf("%d ",&arr); 2 printf("%d ",&arr+1);
这两种输出方式的结果是相差40的
注:数组名是常量 是不能被更改的 下面附上两种错误的写法:arr = arr + 1;或arr++;
5.[]的访问原理:
数组名+下标 === 偏移量 + 间接引用(先偏移 后间接引用)
即arr[0] === *(arr + 0) ……(以此类推)
特殊的是:当间接引用整个数组的地址是 那到的是首元素的地址 即&arr
例:我们想拿到数组中第二个元素的值 我们可以有一下几种不同的表示方法:
1 arr[1]; 2 *(arr+1); 3 *(*&arr+1); 4 (&arr)[0][1];
再放一道典型的例题:
1 #include<stdio.h> 2 int main() 3 { 4 int arr[10] = {0,1,2,3,4,5,6,7,8,9}; 5 printf("%d ",(&arr)[1][-1]); 6 }
这个题输出的结果是9
(&arr)[1]完成后 指的是arr[10]后面的四十个字节 间接引用后 又变成一个int大小的 然后[-1] 指向元素9
(&arr)[1][-1]也可以表示为*(*((&arr)+1)-1)
二.指针数组
1.定义方法:int* arr[5] = {&a,&b,&c,&d,&e};
2.输出数组中的值的两种方法:
1 printf("%d ",*arr[i]); 2 printf("%d ",*(*(arr+i)));
三.数组指针(是指针)
1.定义方法:int (* p) [10] = &arr;
2.输出方式:
①printf("%d ",*(*p+i)); //*p === *&arr
②printf("%d ",p[0][i]);
总结:arr是int*类型 &arr是int* [10]类型
例如:char* arr[5]→(的指针为)char* (* p) [5]
易错点:
1 int* p1,p2;
这行定义中p1是int*类型的 是一个指针 但p2是int型的 是一个变量
四.二维数组
1.定义方法:int arr[2][5];
2.初始化方法:
①完全初始化:int arr[2][5] = {0,1,2,3,4,5,6,7,8,9};
②不完全初始化:int arr[2][5] = {0,1,2,3}; //把值给前面的 后面的为0
③int arr[2][5] = {{0,1,2,3,4},{5,6,7,8,9}};
④int arr[][5] = {0,1,2,3,4,5,6,7,8,9};
3.访问:arr[0][3] = 300;
上面的语句中 arr是二维数组的名 第一个[]表示偏移0个 间接引用 到0的位置 第二个[]表示偏移3个 间接引用 拿到3
注:数组的存储是连续的 arr[1][5] === arr[2][0]
放一道简单的写过的一个类型题:
1 #include<stdio.h> 2 int main() 3 { 4 int arr[2][5] = {0,1,2,3,4,5,6,7,8,9}; 5 printf("%d ",(&arr)[1][1][-8]); 6 }
输出结果为7 这个题上面写过类型题 在这里就不作过多的解释了