杭州seo排名收费相关搜索优化软件
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,其余元素操作系统默认赋值为0a[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表示整个数组,字符串末尾有\0printf("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],是匿名数组