当前位置: 首页 > news >正文

嵌入式c学习六

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],是匿名数组

相关文章:

  • 硬件基础(5):(2)二极管分类
  • 如何编译鲁班猫(LubanCat 1N)固件
  • HTTP/HTTPS
  • 前端小食堂 | Day18 - 身份认证の八卦阵
  • LORA 中的 梯度外积是什么意思; 方差和协方差的实际含义:衡量变量的离散程度和变量间的线性相关性
  • 信息系统运行管理员教程4--信息系统软件运维
  • 【Linux———线程精讲】
  • electron js node vscode 调试electron
  • 实验4 Vue.js路由实验
  • Can通信流程
  • 【Linux网络-数据链路层】以太网(以太网帧格式|MAC地址+模拟一次性局域网通信+MTU)+ARP协议
  • 09 python函数(上)
  • UE学习记录part7
  • 免密登录远程服务器shell脚本
  • 【Linux】:守护进程化
  • 工具层handle_excel
  • Java-泛型总结
  • 蓝桥杯备考:奶牛晒衣服
  • Android NDK --- JNI从入门到基础的全面掌握 (上)
  • github上传本地文件到远程仓库(空仓库/已有文件的仓库)
  • 5145篇报道中的上海车展:40年,什么变了?
  • 持续更新丨伊朗官员:港口爆炸事件已致5人死亡
  • “梅花奖”快闪走入上海张园,朱洁静在石库门前起舞
  • 四川:全省统一取消普通住宅和非普通住宅标准
  • 印巴在克什米尔实控线附近小规模交火,巴防长发出“全面战争”警告
  • 马上评丨喷淋头全是摆设,酒店消防岂能“零设防”