嵌入式学习DAY7 --- 一级指针、二级指针,指针与一维数组

嵌入式入门学习笔记,遇到的问题以及心得体会!
DAY6

笔记:

‘&’ :取址运算符
‘*’ :取值运算符

总结:
指针变量只能用来存地址
可以通过指针变量间接访问(查看/修改)所指向空间的内容

eg:
int a = 100;
int *p = &a;
int b = 80;

&a++;//error
p++;//OK
&a = &b;//error

p = &a;
p = &b;//OK


eg:

int a = 90;
char ch = ‘K’;

int *p = &a; //p一次性访问空间为4字节
p = &ch; //赋值时注意左右两边类型要一致
char *p = &ch; //p一次性访问空间为1字节


练习:实现二维字符数组中多个字符串的排序(5个字符串)


一,二级指针:存储一级指针地址的变量
指针的指针:

(定义意味着有空间
有空间就意味着地址)

如何定义一个一级指针?
存储类型 数据类型 * 指针变量名 ;

如何定义一个二级指针:
存储类型 数据类型 * * 指针变量名;
分析:
存储类型:该二级指针自身的存储类型
数据类型 *:该二级指针所指向的类型
数据类型 ** :该二级指针自身的类型
指针变量名:该二级指针在内存空间中的名字

总结:
(1)如何确定指针变量自身的数据类型?
—》直接去掉【指针变量名】,剩余的均是该指针自身的类型
eg:
int *p; p的类型—》int *
int **pp; p的类型—》int **
char *pp; p的类型—》char **
(2)如何确定指针所指向的数据类型?
----》直接去掉【
指针变量名】,剩余的均是该指针所指向的类型
eg:
int *p ; p所指向的类型是:int
char **pp; pp所指向的类型:char *
(3)如何确定指针一次性访问空间的大小?
----》由指针所指向的类型来决定
eg:
int *p; //p一次性访问空间为4字节
char **pp; //p一次性访问空间为4字节


指针在32OS下占多少个字节?
解释:在32OS下,指针永远占4个字节,因为32OS下内存空间总共为4G这么大,
想要把这4G大的空间用编号表示完全即(0 ~ 4G-1)—>( 0 ~ 2^32-1)
则:可以用32个二进制数字就可以表示完全,32bit == 4bytes
(基于32位操作系统下来说的)


空指针和野指针:

空指针:
值为0的指针,但是值为0的指针用宏定义将其宏定义为NULL
对于值为0的这个字节空间来说,只能被当做初始化来使用,不能访问(查看/修改)其空间里面的值
如果不小心访问了这片空间则会出现段错误

注意:零号地址是禁止被访问的!!

野指针:
指向不明确的指针,杜绝野指针的出现,可以先将其赋值为空指针

总结:
对于空指针:既不能查看,也不能修改
对于野指针:不能修改,但可以查看

出现段错误的原因:
(1)访问了不该访问的空间
(2)越界
(3)修改常量区的内容


二、指针与一维数组:

指针的算术运算: + - * / % ++ –

假设有一个指针变量叫p和q(p和q是同种类型的指针变量):
p + N :代表p向地址增大的方向移动N个数据类型的大小:p + N = p + sizeof(int) *N
p - N :代表p向地址减小的方向移动N个数据类型的大小:p - N = p - sizeof(int) *N
p++: 代表p向地址增大的方向移动一个数据类型的大小:p++ = p + sizeof(int)*1
p–: 代表p向地址减小的方向移动一个数据类型的大小:p-- = p - sizeof(int)*1
p - q :(必须得是同类型之间的指针进行相减)
代表两个指针变量之间相隔数据元素的个数:p-q = (p-q)/sizeof(数据类型)

总结:p++ 和 p+1有什么区别?

p++会引起指针的指向发生改变—》p++ <==> p = p+1;
p+1不会引起指针的指向发生改变

数组名:
(1)能够代表整个数组—》sizeof(数组名) —》可以测得整个数组所占字节空间的大小
(2)代表数组首元素的地址(起始地址/首地址)

打印数组元素的方式:
arr[i] <> *(arr+i) <> *(p+i) <> *(p++) <> p[i] <> i[arr] <> i[p]

注意:数组名是一个地址常量,因此不能进行自加或者自减的运算

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int arr[5] = {1,2,3,4,5};
	//定义一个指针指向该一维数组中的首元素
	int *p = arr;
	printf("sizeof(arr) =  %d\n",sizeof(arr));
	printf("arr = %p\t&arr[0] = %p\n",arr,&arr[0]);
	int i;
	for(i = 0;i<5;i++)
	{
		//printf("%d ",arr[i]);
		//printf("%d ",*(arr+i));
		//printf("%d ",*(arr++));
		//printf("%d ",*(p+i));
		//printf("%d ",*(p++));
		//printf("%d ",p[i]);
		//printf("%d ",i[arr]);
		printf("%d ",i[p]);

	}
	printf("\n");
	return 0;
}

因此:
在算术运算中:地址常量只是不能进行自加和自减的运算,而指针变量均符合该算术运算,
因此不能对数组名进行自加和自减!!!

练习:
1,计算一个字符串中空格的个数(利用指针实现)
2,将整形一维数组的冒泡排序更改为指针的方式(1,不改变指向,2,改变指向)
改变指向如下:

#include <stdio.h>
#define M 5
int main(int argc, const char *argv[])
{
	//定义一个数组
	int arr[M] = {0};
	//定义一个指针指向该数组
	//int *p = &arr[0];
	int *p = arr;

	//完成赋值
	int i,j;
	for(i=0;i<M;i++)
	{
		//scanf("%d",&arr[i]);
		scanf("%d",p+i);
	}

	//输出元素
	for(i=0;i<M;i++)
	{
		//printf("%d ",arr[i]);
		printf("%d ",*(p+i));
	}
	printf("\n");

	printf("冒泡中...\n");
	//控制趟数
	for(i=0;i<M-1;i++)
	{
		p = arr;
		//控制每一趟的次数
		for(j=0;j<M-1-i;j++)
		{
			if(*p > *(p+1))
			{
				int Temp;
				Temp = *p;
				*p = *(p+1);
				*(p+1)  = Temp;
			}
			p++;
		}
	}

	p = arr;
	printf("冒泡之后:\n");
	for(i=0;i<M;i++)
	{
		printf("%d ",*(p+i));
	}
	putchar('\n');
	return 0;
}

不改变指向如下:

#include <stdio.h>


#define M 5
int main(int argc, const char *argv[])
{
	//定义一个数组
	int arr[M] = {0};
	//定义一个指针指向该数组
	//int *p = &arr[0];
	int *p = arr;

	//完成赋值
	int i,j;
	for(i=0;i<M;i++)
	{
		//scanf("%d",&arr[i]);
		scanf("%d",arr+i);
	}

	//输出元素
	for(i=0;i<M;i++)
	{
		//printf("%d ",arr[i]);
		printf("%d ",*(arr+i));
	}
	printf("\n");

	printf("冒泡中...\n");
	//控制趟数
	for(i=0;i<M-1;i++)
	{
		//控制每一趟的次数
		for(j=0;j<M-1-i;j++)
		{
			if(*(arr+j) > *(arr+j+1))
			{
				int Temp;
				Temp = *(arr+j);
				*(arr+j) = *(arr+j+1);
				*(arr+j+1)  = Temp;
			}
		}
	}

	printf("冒泡之后:\n");
	for(i=0;i<M;i++)
	{
		printf("%d ",*(arr+i));
	}
	putchar('\n');
	return 0;
}



三、指针与二维数组:

作业:
1,实现二维字符数组中多个字符串的排序(5个字符串)—》用数组方式

#include <stdio.h>
#include <string.h>


#define M 5
#define N 20
int main(int argc, const char *argv[])
{
	//实现5个字符串的排序输出
	char str[M][N] = {'\0'};

	printf("请输入:\n");
	int i,j;
	for(i=0;i<M;i++)
	{
		scanf("%s",str[i]);
	}

	printf("输出为:\n");
	for(i=0;i<M;i++)
	{
		printf("%s\n",str[i]);
	}

	printf("冒泡中:.....\n");
	for(i=0;i<M-1;i++)
	{
		for(j=0;j<M-1-i;j++)
		{
			if(strcmp(str[j],str[j+1]) > 0)
			{
				//交换
				char Temp[N] = {'\0'};
				strcpy(Temp,str[j]);
				strcpy(str[j],str[j+1]);
				strcpy(str[j+1],Temp);
			}
		}
	}

	printf("排序之后:\n");
	for(i=0;i<M;i++)
	{
		puts(str[i]);
	}
	return 0;
}

2,利用指针实现strcat和strcpy
strcat:

#include <stdio.h>

#define M 20
#define N 10
int main(int argc, const char *argv[])
{
	//利用指针实现strcat的功能
	char str1[M] = {'\0'};
	char str2[N] = {'\0'};

	char *pStr1 = str1;
	char *pStr2 = str2;

	printf("请输入:\n");
	gets(pStr1);
	gets(pStr2);

	printf("连接之前:str1  = %s\n",pStr1);
	//遍历str1这个字符串至末尾第一个'\0'处
	while(*pStr1)
	{
		pStr1++;
	}

	//再遍历str2这个字符串,并将每一个有效字符连接在str1的后面
	while(*pStr2)
	{
		*pStr1++ = *pStr2++;
	}

	pStr1 = str1;
	printf("连接之后:str1 = %s\n",pStr1);
	return 0;
}

3,利用指针将一个字符串进行翻转:“break” <–>“kaerb”

#include <stdio.h>
#include <string.h>

#define M 20
int main(int argc, const char *argv[])
{
	//实现字符串的倒置
	char str[M] = {'\0'};
	char *p = str;
	char *q = p;//指针变量之间可以相互赋值
	gets(p);

	//第一种:让q指向末尾最后一个有效字符
	//q = q + strlen(str) - 1;
	//第二种:让q指向最后一个有效字符
	while(*q)
	{
		q++;
	}
	q--;
	
	while(p < q)
	{
		//交换
		char Temp;
		Temp = *p;
		*p = *q;
		*q = Temp;
		p++;
		q--;
	}
	p = str;
	printf("倒置之后的结果为: %s\n",p);


	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值