前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >day7嵌入式(2022.1.13)

day7嵌入式(2022.1.13)

作者头像
天天Lotay
发布2022-12-02 14:31:36
1780
发布2022-12-02 14:31:36
举报
文章被收录于专栏:嵌入式音视频

数组指针,指针数组

代码语言:javascript
复制
#include<stdio.h>

int main()
{
	int a = 100;
	int *p1 = &a;	// 整型指针

	char ch = 'A';
	char *p2 = &ch;	// 字符型指针

	int arr[5] = {1, 3, 5, 7, 9};
	int *p3 = arr;	// 整型指针,指向整型1
	
	int (*p4)[5] = &arr;	// arr整个数组的地址
		// 数组指针

	int *p5[5];
	printf("size: %ld\n", sizeof(p5));	// 5*8=40字节

	char *str1 = "hello";
	printf("str1: %s\n", str1);

	// 字符串数组
	char *str[5] = {"hello", "world", "nihao", "hahaha", "xixixi"};
	printf("str[0]: %s\n", str[0]);
	printf("str[1]: %s\n", str[1]);
	printf("str[2]: %s\n", str[2]);
	printf("str[3]: %s\n", str[3]);
	printf("str[4]: %s\n", str[4]);

	return 0;
}

函数指针,指针函数

代码语言:javascript
复制
#include<stdio.h>

// 计算和(函数的声明)
int func_sum(int a, int b);
int *func_1(int a);

int main()
{
	// 函数调用原理:根据<函数入口地址>去执行对应函数。
	int c1 = func_sum(100, 200);
	printf("c1: %d\n", c1);

	// 函数类型:返回值 + 形参列表(函数头)
	// 函数名就是函数的入口地址。
	int (*p1)(int, int) = func_sum;
	int c2 = p1(300, 400);
	printf("c2: %d\n", c2);

		// 假设已知某个函数的入口地址为 0x000000FF
	// (一般用于硬件代码中,因为软件程序中函数的地址都是随机分配的。)
	// int (*p2)(int, int) = 0x000000FF;
	// int c3 = 0x000000FF(300, 400);	// 直接调用入口地址为 0x000000FF的函数
	// printf("c3: %d\n", c3);

	int *p2 = func_1(100);
	printf("p2: %p\n", p2);

	return 0;
}

int *func_1(int a)
{
	int *p1 = &a;
	printf("p1: %p\n", p1);

	return p1;
}

// 计算和(函数的定义)
int func_sum(int a, int b)
{
	return a+b;
}

函数的传递

代码语言:javascript
复制
#include<stdio.h>

// 值传递(只是将数值100, 200传参)
void func_swap1(int a, int b);

// 地址传递(将数值本身的地址传递过去)
void func_swap2(int *a, int *b);

int main()
{
	int n1=100, n2=200;
	printf("n1:%d n2:%d\n", n1, n2);
	// func_swap1(n1, n2);	// 值传递,不能修改变量本身
	func_swap2(&n1, &n2);
	printf("n1:%d n2:%d\n", n1, n2);

	return 0;
}

// 地址传递(将数值本身的地址传递过去)
//		int *a = &n1;
//		int *b = &n2;
void func_swap2(int *a, int *b)
{
	int c;
	c = *a;
	*a = *b;
	*b = c;

	printf("func_swap: a:%d b:%d\n", *a, *b);
}

// 值传递(只是将数值100, 200传参)
//		int a = n1;
//		int b = n2;
void func_swap1(int a, int b)
{
	int c;
	c = a;
	a = b;
	b = c;

	printf("func_swap: a:%d b:%d\n", a, b);
}

==================== 1.地址偏移量概念 ========================

指针算术运算,可以跟数组形式相互转换

*(p+i) <==> p[i]

备注:

  1. 数组名不能作为等号的左值。

int a[5];

printf("%d ", *(a++));

printf("%d ", *(a=a+1));

  1.  []的优先级是高于解引用*
  2. 对数组地址进行解引用,会得到数组的首元素地址。
  3. 数组首元素地址和数组本身地址:

int a[5] = {1, 3, 5, 7, 9};

printf("a   : %p\n", a);    // 数组首元素地址

printf("&a  : %p\n", &a);   // 数组本身地址

// 上述两个地址在数值上是一样的,但是类型不相同。

printf("a+1 : %p\n", a+1);  // 向右偏移4字节(类型:int *)

printf("&a+1: %p\n", &a+1); // 向右偏移20字节(类型:int (*)[5])

 2.数组指针、指针数组、函数指针、指针函数 ========================

  1. 数组指针:指向数组的指针。(也称为行指针,指向二维数组一行数据)

int (*p4)[5]; // 该指向指向  int [5]类型的数组

作用:一般用于二维数组访问。

  1. 指针数组:存储着一系列的相同类型指针的数组。

int *p4[5]; // 该数组存储着5个指针(类型为 int *)

(数组三要素:连续内存+具体长度+相同类型)

作用:存储多个值,指向多个数据

  1. 函数指针:指向函数类型的指针。

int (*p1)(int, int) = func_sum; // 该指针指向函数 func_sum

作用:直接通过指针调用函数。(如回调函数)

  1. 指针函数:返回值为指针的函数(返回地址)

int *func_1(int a) // 返回值为int *

如果返回值为 void *,表示返回无值型指针(任意类型指针)。

循环遍历二维数组

代码语言:javascript
复制
#include<stdio.h>

// *(p+i) <==> p[i]
int main()
{
	// int arr[2][3] = {1, 3, 5, 2, 4, 6};
	int arr[2][3] = {{1, 3, 5}, {2, 4, 6}};	//更为规范的写法

	// int *p1 等同于 int (*p1)
	// int *p1 = arr; 	// 错误写法。类型不匹配。
//	int *	= int (*)[3] 
// 	整型指针 = 数组指针

	int *p2 = &arr[0][0];	// 类型匹配
//	int *	= int *
// 	整型指针 = 整型指针

	int (*p3)[3] = arr;		// 类型匹配
//	int (*)[3]   = int (*)[3]
// 	数组指针      = 数组指针

// 1.通过数组名访问
	int i, j;
	for(j=0; j<2; j++)
	{
		for(i=0; i<3; i++)
			printf("%d ", arr[j][i]); 
			// printf("%d ", *(*(arr+j)+i)); 
			// printf("%d ", *(arr[j]+i)); 
			// printf("%d ", (*(arr+j))[i]); 
				// 上述四种写法效果一模一样。

			// printf("%d ", *(arr+j)[i]); 	// 错误写法。因为[]优先级高于解引用*
		printf("\n");
	}

// 2.通过整型指针访问
	printf("==============================\n");
	for(i=0; i<2*3; i++)
		// printf("%d ", *p2++);
		// printf("%d ", *(p2+i));
		printf("%d ", p2[i]);
	printf("\n");

// 3.通过数组指针访问
	printf("==============================\n");
	for(j=0; j<2; j++)
	{
		for(i=0; i<3; i++)
			// printf("%d ", p3[j][i]); 	// arr[j][i]
			printf("%d ", *(*(p3+j)+i)); 
			// printf("%d ", *(p3[j]+i)); 
			// printf("%d ", (*(p3+j))[i]); 
				// 上述四种写法效果一模一样。
		printf("\n");
	}

	return 0;
}

循环遍历一维数组

代码语言:javascript
复制
#include<stdio.h>
int main()
{
	int a[5] = {1, 3, 5, 7, 9};
	// int *p1 = &a[0];		// 定义指针,指向首元素a[0]
	int *p1 = a;			// 数组名就是首元素地址
//	int *	= int *	   类型匹配!

	printf("1: %p\n", p1);

	for(int i=0; i<5; i++)	// 0 1 2 3 4
	{
		// 写法1.1:指针本身进行偏移
		// printf("%d ", *p1);	// 对指针进行解引用
		// p1++;	//p1 = p1+1; //p1+=1;
		// 写法1.2
		// printf("%d ", *p1++);	// ++优先级更高,但是它作为后缀,必须在运算结束后再自加
		// printf("%d ", *(p1++));	// 等同于上一行
		// printf("%d ", (*p1)++);	// 错误写法。解引用后都是获得数据1。

		// 写法2:指针进行运算
		// printf("%d ", *p1+i);	// 错误写法。解引用*的优先级高于+
		// printf("%d ", *(p1+i));	// 正确写法。
		// printf("%d ", *(i+p1));	// 正确写法。
		
		// 写法3:指针运算(数组形式,地址偏移量)
		// printf("%d ", p1[i]);
		// printf("%d ", i[p1]);
		// printf("%d ", a[i]);
		// printf("%d ", i[a]);
		// printf("%d ", *(a+i));
		// printf("%d ", *(i+a));

		// printf("%d ", *(a++));	//错误写法:数组名不能自增自减。*(a=a+1)
	}
	printf("\n");

	int arr[2][3] = {1, 3, 5, 2, 4, 6};

	printf("2: %p\n", p1);

	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档