数组就是一个能够一次性定义多个相同类型的变量,并能够放到一个连续的内存中去。
数组
只有在定义的时候顺便赋值才叫初始化。测试
int a = 1024 ; int arr[5] = {1,2,3,4,5}; // 彻底初始化 int arr1[] = {1,2,3,4,5,6,7,8,9,10} // 正确,定义的时候并无肯定大小, 初始化后才肯定的大小 arr2 = {1,2,3,4,5,}// 不可行, 数组只有在初始化的时候能够统一赋值 int arr2 [5] = {1,2,3,4,5,6,7}; // 语法上能够,可是逻辑上不容许, 涉嫌越界 int arr3[50] = {1,2,3,4,5}; // 不彻底初始化 , 没有初始化部分自动填充0
数组名在不一样的环境中表示的意思不同3d
a.在定义的时候 int a[10];
b.在sizeof(a)语句中;
c.在取地址&a时。指针
a.除了上面三种状况之外,其余全部状况都表示首元素的首地址。code
存储方式:一片连续的内存空间,按照具体的数据类型进行分割
数组下标:以数组首地址为起点的偏移量
blog
int arr1[5] = {1, 2, 3, 4, 5}; printf("arr1[1]:%p\n", &arr1[1]); printf("arr1[2]:%p\n", &arr1[2]); printf("arr1[3]:%p\n", &arr1[3]); printf("arr1[4]:%p\n", &arr1[4]); printf("arr1[5]:%p\n", &arr1[5]); //输出结果,可得相邻的数组元素地址相差4,与数组的类型所占的大小相等 arr1[1]:0x7fffeec8c1f4 arr1[2]:0x7fffeec8c1f8 arr1[3]:0x7fffeec8c1fc arr1[4]:0x7fffeec8c200 arr1[5]:0x7fffeec8c204
注意:
1.一位数组中arr表示首元素的起始地址,&arr表示整个数组的起始地址,虽然值是同样的可是表明的意义却不同;
2.arr+1与arr[1],arr+2与arr[2].....arr+n与arr[n]是相同的意思;
3.a[1]与1[a],a[2]与2[a]....a[n]与n[a]是相同的意思。内存
专门用来存放字符数据的数组,成为字符数组。字符串
char s1 [5] = {'a' ,'b' , 'c' ,'d' , 'e'}; // 中存放的是字符数据 char s2 [6] = {'a' ,'b' , 'c' ,'d' , 'e' , '\0'}; // 中存放的是字符串数据 char s3 [6] = {"hello"} ; // s3中存放的是字符串 , 注意数组大小必须能完整存储下整个字符串包括结束符 char s4 [6] = "hello"; // 使用双引号的时候大括号能够省略 s4[1] = 'E' ; printf("s1:%s\n" , s1 ); // 注意该数组为字符数组,不该该使用%s来访问输出,他会涉嫌越界,%s须要遇到'\0'才愿意停下来 printf("s2:%s\n" , s2 ); // 常规操做 printf("s2:%s\n" , s2+2 ); s2+2 加了两个 char 的大小 , printf("s3:%s\n" , s3 ); printf("s4:%s\n" , s4 );
二维数组能够理解为:数组内容为数组。
it
/* 测试代码 */ int arr[3][3] = {{1, 11, 111} , {2, 22, 222} , {3, 33, 333}}; printf("&arr: %p\n", &arr); printf("&arr+1:%p\n", &arr+1); printf("arr[0][0]:%p\n", *arr+0); printf("arr[0][1]:%p\n", *arr+1); printf("arr[0][2]:%p\n", *arr+2); printf("arr[0][0]:%p\n", *(arr+0)); printf("arr[1][0]:%p\n", *(arr+1)); printf("arr[2][0]:%p\n", *(arr+2)); printf("arr[0][1]:%d\n", *(*(arr+0)+0)); printf("arr[0][2]:%d\n", *(*(arr+0)+1)); printf("arr[0][3]:%d\n", *(*(arr+0)+2));
注意:
1.若是将代码中的&arr,arr+0,(arr+0)传递给相应的指针,其所表明的意义也将传递给指针。变量
长度为零的数组
int a[0];
其主要的功能是放在结构体的末尾,做为结构的最后一个成员,能够做为结构体内存扩容入口,数组是C语言中惟一一个容许越界访问的东西。
越界访问:只是访问原本不属于某个变量的内存(数组本来申请大区域)不必定就是非法访问
越界是访问的内存只要都属于我当前程序所用的内存就不属于非法访问。
非法访问:访问的内存地址不属于你这个程序的内存。
概念: 在定义数组以前可能他的长度是未知的, 定义语句执行后他的长度是固定的。
重点: 在定于语句中数组的长度是一个变量,定义结束以后即便长度的变量有所变化也不会影响数组的长度了。
说白了就是数组的长度是一个变量;
int i = 90 ; 。。。 。。 int buf[ i ] ; int a = 10 ; int arr[ a ] = {0} ; // error: variable-sized object may not be initialized
注意:
变长数组不能够初始化。
用来存放指针的数组
int * arr[5] ; int a , b ,c ,d, e ; arr[0] = &a ; arr[1] = &b ; char * str [3] = {"Hello" , "GZ2075" , "eVEN"}; for (int i = 0; i < 3; i++) { printf("str[%d]:%s\n" , i , str[i]); }
常量:不能够被修改的量
存储在常量区的字符串数据称为字符串常量,其实是一个匿名数组
printf("%d\n" , sizeof("GZ2075")); // "GZ2075"表示的整个数组 printf("%p\n" , &"GZ2075"); // "GZ2075"表示的整个数组 printf("%c\n" ,"GZ2075"[1]); // 使用与数组相似的方法来访问某一位元素 char * p1 = "GZ2075" ; // p1指向 "GZ2075" 匿名数组的首元素的首地址 char * p2 = "GZ2075" + 1; // p2 指向 "GZ2075" 匿名数组的第二个元素 ‘Z’
注意: 字符串常量都是以'\0'结尾的,不可忽略它的存在。