**c语言的数组:**用户向内核申请一块连续的空间来存储数据,存储数据的类型需要一致,避免二义性Array
**数组的定义:**数据类型 数组名称 [数据个数],内存大小为:数据类型*数据个数------如:int a[3];
**[数据个数]:**是一个表达式,用于制定数组的大小,如果表达式是一个常量,应该是大于0的一个整数
**数组的访问:**访问数组中的元素可以采用E1[E2]结构------>E1是数组对象,E2是一个整数,作为数组的下标,且数组下标从0开始;数组的名称是指向数组对象的指针->数组名表示数组首元素地址
E1[E2] = *(E1+E2)---------> a[3] = *(a+3)---------》E1是数组名,E2是整型常量
***运算符:**①作为二元运算符,表示乘法,需要两个操作对象,遵循左结合性;
②作为一元运算符其操作对象对应的类型应该为地址,遵循右结合性,*操作数 == *地址==可以得到地址下的数据
&取地址运算符: 向右结合性,&操作数 可以得到操作数的地址
*(E1+E2): E1是一个数组对象,即数组名称,c语言规定数组名可以表示数组中第一个元素的地址,就相当于E1数组中第一个元素的地址,E2是一个整数,加上E2表示从E1的地址向后偏移E2个元素(需要考虑元素类型),(E1+E2)还是地址,*(E1+E2)相当于间接访问该地址得到对应的值,即*(E1+E2)==E1[E2]------》E1[E2] == E2[E1],这两种方式都哦可以访问数组中的元素。
#include <stdio.h>
int main()
{
char buf[11];
buf[0] = 'a';
buf[1] = 'b';
buf[2] = 'c';
buf[3] = 'd';
4[buf] = 'e'; //E1[E2],E1是数组名,E2是整型常量,E1[E2]------》*(E1+E2)------》E2[E1]
5[buf] = 'f';
6[buf] = 'g';
7[buf] = 'h';
7[buf] = '\0';
printf("%s\n", buf);
return 0;
}

**&运算符:**①二元运算符------表示按位与
②一元运算符:&操作数,可以得到操作数的地址,遵循右结合性
*&E == E------》&E结合得到E的地址,*(&E)得到地址下的值,变量名E本身就表示地址下的值
#include <stdio.h>
int main()
{
int data;
data = 10; //对变量赋值
printf("data=%d\n", data);
*&data = 20; //同样可以赋值
printf("data=%d\n", data);
return 0;
}

**数组名的含义:**c标准中说明数组名可以表示数组首元素地址,有两种例外情况,如a是一个数组
**&a:**此时a表示数组本身,&a表示整个数组的地址
#include <stdio.h>
int main()
{
int a[5];
printf("%p->%p\n", a, &a[0]); //此时a表示首元素地址
printf("%p->%p\n", a+1, &a[1]); // a+1表示数组第二个元素的地址
printf("%p->%p\n", &a, &a+1); //&a表示整个数组的地址其值与数组首元素地址相同,&a+1表示以数组本身为单位向后偏移一个数组的大小即4*5=20字节
return 0;
}

0x44-0x30 = = 0x14 == 20(字节)
sizeof(a): 当数组名与sizeof()运算符单独运算时,表示数组本身
#include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
printf("%d\n", sizeof(a)); //20------>数组a与sizeof()运算符单独使用,a表示数组本身大小为 20字节
printf("%d\n", sizeof(a+0)); //8------>未单独使用,a表示首元素地址,a+0为地址偏移量为0,64bit系统中地址为8字节
printf("%d\n", sizeof(*a)); //4------>a表示首元素地址,*表示取地址里面的数据,整型未4字节
printf("%d\n", sizeof(a[1])); //4------>a[1]数组第二个元素的值,数据大小4字节
printf("%d\n", sizeof(&a)); //8------>&a表示数组本身地址-》8字节
printf("%d\n", sizeof(&a+1)); //8------>地址偏移一个数组单位的字节
printf("%d\n", sizeof(&a[0]));//8->首元素地址
printf("%d\n", sizeof(&a[0]+1));//8->首元素地址,偏移单位未数组中的元素类型
char a[5] = {'a', 'b','c','d','e'};
printf("%d\n", sizeof(a)); //5------>数组a与sizeof()运算符单独使用,a表示数组本身大小为 20字节
printf("%d\n", sizeof(a+0)); //8------>未单独使用,a表示首元素地址,a+0为地址偏移量为0,64bit系统中地址为8字节
printf("%d\n", sizeof(*a)); //1------>a表示首元素地址,*表示取地址里面的数据,整型未4字节
printf("%d\n", sizeof(a[1])); //1------>a[1]数组第二个元素的值,数据大小4字节
printf("%d\n", sizeof(&a)); //8------>&a表示数组本身地址-》8字节
printf("%d\n", sizeof(&a+1)); //8------>地址偏移一个数组单位的字节
printf("%d\n", sizeof(&a[0]+1));//8->首元素地址,偏移单位未数组中的元素类型
return 0;
}


**数组的初始化:**c语言规定只有在定义数组的同时进行赋值才叫数组初始化,
**格式:**数据类型 数组名[数组容量] = {0}; 如 int a[5] = {0,0,0,0,0};
int main()
{
int a[5] = {1}; // 将数组第一个元素初始化未1,其余元素操作系统默认赋值为0
a[4] = 10; //此处是对数组元素进行赋值不叫初始化
for(int i =0; i<5; i++){
printf("a[%d]=%d\n", i, a[i]);
}
return 0;
}

**[数组容量]:**用户在定义时数据此处可以空着不写,一般需要在定义的同时进行初始化,操作系统会直接以用户初始化数据的个数申请内存空间
#include <stdio.h>
int main()
{
int a[] = {1,2,3,4,5,6}; // 将数组初始化未,操作系统将申请6个整型数据的内存
printf("%d\n", sizeof(a)/sizeof(a[0]));
return 0;
}

数组元素的清空 :bzero()函数与memset()函数
**bzero():**需要包含头文件<strings.h>,void bzero(void *s, size_t n),将参数s指向的地址区域的前n个字节清0(存的是'\0'的ASCII码),无返回值
**memset():**void *memset(void *s, int c, size_t n),将参数s所指向区域的地址的前n个字节填充为c,返回值为s指向的内存地址
#include <stdio.h>
#include <strings.h>
#include <string.h>
int main()
{
int buf[5] = {1,2,3,4,5};
printf("修改前\n");
for(int i=0; i<5; i++){
printf("buf[%d]=%d ", i, buf[i]);
if(i == 4){
printf("\n");
}
}
memset(buf,0,4); //将数组中前4个字节设置为0,即数组中第一个元素设置为0
printf("修改后\n");
for(int i=0; i<5; i++){
printf("buf[%d]=%d ", i, buf[i]);
}
printf("\n");
return 0;
}

数组越界访问,可能会出现段错误------>访问没有权限访问的空间
字符型数组: 字符串末尾需要以'\0'结尾,如char a[5] = "abcde" ------>此处系统为默认在结尾加'\0',已经出现越界访问,因此数组中有效字符串常量,应该小于数组容量
#include <stdio.h>
int main()
{
char a[]="adcd";
//32bit系统寻址能力为4个字节
printf("sizeof(a) = %d\n", sizeof(a)); //5-> a表示整个数组,字符串末尾有\0
printf("sizeof(a+0) = %d\n", sizeof(a+0)); //4-> a表示首元素地址->+0表示偏移0个字符型元素
printf("sizeof(*a) = %d\n", sizeof(*a)); //1-> *a等价与a[0]
printf("sizeof(a[1]) = %d *(a+1) = %d\n",
sizeof(a[1]), sizeof(*(a+1))); //1->*(a+1) == a[1]
printf("sizeof(&a) = %d\n", sizeof(&a)); //4-> a表示数组本身,&a表示数组的地址
printf("sizeof(&a+1) = %d\n", sizeof(&a+1)); //4-> &a+1表示地址向后偏移一个数组的大小
printf("sizeof(&a[0]+1) = %d\n", sizeof(&a[0]+1)); //4-> &a[0]表示首元素地址,&a[0]+1,地址偏移一个元素(字符型)单位
printf("sizeof(&a[0]+1) = %d\n", sizeof(&a[0]+1));
return 0;
}

**数组型数组:**多维数组,维度是针对用户而言,内存是线性的不分行和列。
**定义规则:**数组名[元素数量] + 元素类型 如:int a[5]
**二维数组定义规则:**元素类型 数组名称[元素数量] [元素数量] 如:int a[3][2]
可通过下标访问:a[1][2] == *(a+1)[2] == *(*(a+1) +2)
#include <stdio.h>
int main()
{
int a[2][3]={{1,2,3},{4,5,6}};
printf("a[1][2]=%d\n", a[1][2]);
printf("*(*(a+1)+2)=%d\n", *(*(a+1)+2)); //E1[E2] == *((E1) + (E2))
return 0;
}

#include <stdio.h>
int main()
{
int a[3][4] = {0}; //将第一个元素初始化为0,其他元素系统默认置0
//数组a: a[0] a[1] a[2]
// 0 0 0 0___0 0 0 0___0 0 0 0
// a[0][0] a[1][0] a[2][0]
printf("sizeof(a)=%d\n", sizeof(a)); //48:a表示整个数组
printf("sizeof(a[0][0])=%d\n", sizeof(a[0][0])); //4 :表示第一个元素的值
printf("sizeof(a[0])=%d\n", sizeof(a[0])); //16:a[0]表示匿名数组 int [4]
printf("sizeof(a[0]+1)=%d\n", sizeof(a[0]+1)); //4 :a[0]表示匿名数组int [4]的首元素地址
printf("sizeof(*(a[0]+1))=%d\n", sizeof(*(a[0]+1))); //4 :*(a[0]+1) == a[0][1]
printf("sizeof(a+1)=%d\n", sizeof(a+1)); //4 :a表示首元素地址a[0]的地址,a[0]是个数组
printf("sizeof(*(a+1))=%d\n", sizeof(*(a+1))); //16:*(a+1) == a[1]
printf("sizeof(&a[0]+1)=%d\n", sizeof(&a[0]+1)); //4 :&a[0]表示a[0]数组的地址+1=&a[1]
printf("&a[0]+1=%p &a[1]=%p\n",&a[0]+1, &a[1]);
printf("sizeof(&a[0]+1)=%d\n", sizeof(*(&a[0]+1))); //16: *&a[1] == a[1] *与&互相抵消
printf("sizeof(*a)=%d\n", sizeof(*a)); //16: a表示首元素地址即&a[0], *&a[0]==a[0]
//16: *a = *(a+0) = a[0]
printf("sizeof(a[3])=%d\n", sizeof(a[3])); //16:a[3]已经越界,可以保存地址,但不能访问内存
return 0;
}

**柔性数组:**数组元素的数量用变量来表示,注意数组内存一旦确定就不会因为变量发生变化导致数组长度变化
#include <stdio.h>
int main()
{
int cnt =5;
int a[cnt];
printf("%d\n", sizeof(a));
cnt = 0;
printf("%d\n", sizeof(a));
return 0;
}

**匿名数组:**一般在多为数组中使用。如:int a[3][4]--->数组a[3]中每个元素为int [4],是匿名数组