(Linux)嵌入式打卡第九天

指针

前言

相关概念:

  1. 地址:在arm架构的计算机中,地址是一块连续的空间。地址中的每一个字节都有一个编号,这个编号就称之为地址。
  2. 指针:指针是一个数据类型
  3. 指针变量:本质是一个变量,变量里面存地址。

在后续学习中,工作中,以上三个概念统称为 指针

指针变量的定义格式:

格式:
    <数据类型> *指针名 = value;
         |    |   |       |-------->地址
         |    |   |---------------->变量名:符合变量的命名规则
         |    |-------------------->*是一个指针的标识
         |------------------------->指针的类型
eg:
    int number = 10;
    int *p = &number;//定义一个变量p,变量p里面存放的内容是number的地址;
                     //指针p里面存放的是number的地址,称之为 p指向number

与指针相关的运算符

& 运算符 :取地址运算符,(获取的是变量的地址),注意: & 是不可以获取常量的地址的。
         对于多字节变量,取地址运算符,取得是首地址,标号最小的那个值。
    eg:
#include <stdio.h>

int main(int argc, const char *argv[])
{
	//定义一个指针,指针执行一个int的地址
	//int *p = %10;//10是一个int类型的常量,error
	//& 运算符只能获取变量的地址
	//定义一个变量number
	int number = 10;
	printf("&number = %p\n",&number);

	return 0;
}
*取值运算符:获取地址所指向空间的使用权; *指针;
    左值:等号左边的值,叫做左值;
        *指针 = value; 获取指针所指向的空间,并且将右值value赋值到这个空间。
    右值:等号右边的值,叫做右值;
        *指针; 没有 = 的时候默认为右值;
        *指针; 获取指针空间里的值。
    简单记忆:
        *指针 与 变量名 是等价的。

课堂代码:
#include <stdio.h>

int main(int argc, const char *argv[])
{
	//定义一个char类型的变量
	char ch = 'a';//在内存中申请一个变量 变量里面存放‘a’

	//定义一个变量,用来存放ch的地址
	char *p = &ch;  //*是不是运算符? 
	                //这里的*表示的不是运算符     
				    //只代表了定义一个char* 类型的指针变量。

	//*运算符:
	*p = 'A';//*运算符:*p是左值,获取指针p所指向的空间
			 //并将右值赋值给这个空间

	printf("ch = %c,*p = %c\n",ch,*p);//*p是没有=的,所以默认为右值
	//*p 获取指针指向空间里面的值
	
	return 0;
}
#include <stdio.h>

int main(int argc, const char *argv[])
{
	//1.定义一个 int 类型的变量,名为a
	int a = 10; // 操作系统会根据变量的类型给变量分配空间

	//2.通过变量名对这块空间进行修改
	a = 20;

	//3.查看操作系统分配空间,分配到了那里?
	printf("&a = %p\n",&a);// 获取 a 的地址;

	//4.将a的地址保存到变量中
	int *p1 = &a;//定义一个变量p1,p1里面保存变量 a 的地址。

	printf("p1 = %p\n",p1);
	
	//5.地址是一个数字,指针又是保存这个地址的变量
	int *p2 = 0x1234; //waring:指针只能保存系统分配了的地址

	//*p2 = 200;   //error:使用了未分配的地址
	printf("p2 = %p\n",p2);


	//6.地址是一个数字,能否使用变量来保存这个地址
	long value = &a;//可以保存但是有警告

	//*value = 20;error:可以保存,但是不能进行*取值操作
	
	//7.指针变量的申请:
	
	int b,c;//定义了两个变量b,c,b与c的类型都是 int 类型;
	int *pa,pb;//定义了两个变量pa,pb, pa的类型是指针,pb的类型是int类型的变量
	int *pc,*pd;//定义了两个指针 pc,pd

	return 0;
}
结果:
&a = 0x7ffcc80bdeac
p1 = 0x7ffcc80bdeac
p2 = 0x1234

指针的基本使用

#include <stdio.h>

void swap1(int x,int y)
{
	int ret = x;
	x = y;
	y = ret;
}
void swap2(int *x,int *y)
{
	int *ret = x;
	x = y;
	y = ret;
}
void swap3(int *x,int *y)
{
	int ret = *x;
	*x = *y;
	*y = ret;
}
void swap4(int *x,int *y)
{
	int *ret;
	*ret = *x;
	*x = *y;
	*y = *ret;
}
void swap5(int *x,int *y)
{
	//改进swap4
	int value;//在内存中申请一块变量
	int *ret = &value;
	*ret = *x;
	*x = *y;
	*y = *ret;
}
int main(int argc, const char *argv[])
{
	int x = 5;
	int y = 10;

	printf("未调用之前:x = %d,y = %d\n",x,y);
	swap5(&x,&y);

	printf("调用函数之后:x = %d,y = %d\n",x,y);

	return 0;
}

野指针与空指针

野指针

指向一块未确定的区域。

(1)int *p; //指针没有赋初值,p执行的地址:随机的空间

(2)int number = 10;
     int *p;
     p = &number; //不是野指针:指针p指向的空间是number

野指针的危害:
    (1)报错:野指针有可能会造成 段错误 ,代码不能正常运行。
    (2)不报错:未知错误;

    #include <stdio.h>

int main(int argc, const char *argv[])
{
	//*p就是一个野指针
	int *p;
	*p = 200; //向一个未知区域赋值

	//假设不报错的情况
	int array[10] = {1,2,3,4,5,6,7,8,9,10};
	//target: 打印数组里面的值
	
	
	int *q;//野指针 q里面刚好就是array[4]的地址

	*q = 200;
	//将array[4] = 200;

	return 0;
}

空指针

在指针定义的时候,不知道指针用哪个地址初始化,可以先将指针指向NULL;

指向NULL的指针,就称之为空指针;

eg:

int *p = NULL; //

// NULL 就是 0 地址;0 地址是不允许用户操作的。

* 或 & 运算符进行运算的时候,会立马报错。

作用:

使用空指针,可以在一定程度上避免野指针的错误。

指针占内存的大小

32位计算机中,无论是什么类型的指针,全部在内存中占 4 字节。

64位计算机中,无论是什么类型的指针,全部在内存中占 8 字节。

#include <stdio.h>

int main(int argc, const char *argv[])
{
	char *p1 = NULL;
	short *p2 = NULL;
	int *p3 = NULL;
	long *p4 = NULL;
	long long *p5 = NULL;
	float *p6 = NULL;
	double *p7 = NULL;

	printf("sizeof(char *) = %ld, sizeof(p1) = %ld\n",sizeof(char *),sizeof(p1));
	printf("sizeof(short *) = %ld, sizeof(p2) = %ld\n",sizeof(short *),sizeof(p2));
	printf("sizeof(int *) = %ld, sizeof(p3) = %ld\n",sizeof(int *),sizeof(p3));
	printf("sizeof(long *) = %ld, sizeof(p4) = %ld\n",sizeof(long *),sizeof(p4));
	printf("sizeof(long long *) = %ld, sizeof(p5) = %ld\n",sizeof(long long *),sizeof(p5));
	printf("sizeof(float *) = %ld, sizeof(p6) = %ld\n",sizeof(float *),sizeof(p6));
	printf("sizeof(double *) = %ld, sizeof(p7) = %ld\n",sizeof(double *),sizeof(p7));



	return 0;
}
结果:
sizeof(char *) = 8, sizeof(p1) = 8
sizeof(short *) = 8, sizeof(p2) = 8
sizeof(int *) = 8, sizeof(p3) = 8
sizeof(long *) = 8, sizeof(p4) = 8
sizeof(long long *) = 8, sizeof(p5) = 8
sizeof(float *) = 8, sizeof(p6) = 8
sizeof(double *) = 8, sizeof(p7) = 8

指针类型的作用

在C语言中:

数据类型的作用在于:表示在内存中申请指定大小的空间。

指针在内存中申请:4 /8个字节。

指针的作用

<1>通过 *(取地址运算符运算的时候) 向后取几个字节的空间   (4或8个字节)
int a = 10; //假设 a
int *p = &a;

编写程序:判断自己的电脑是大端还是小端。
#include <stdio.h>

int main(int argc, const char *argv[])
{
	unsigned int number = 0x12345678;
	int *p = &number;
	if(*((char*)p) == 0x12)
	{
		printf("计算机是大端机\n");
	}
	else if((*(char*)p) == 0x78)
	{
		printf("计算机是小端机\n");
	}
	else
	{
		//保证语法的完整性
	}

	return 0;
}
结果:
计算机是小端机

指针运算

指针里面存放的都是地址编号;指针里面的运算,就是地址的运算。

指针的运算:在连续空间中才有意义。

指针支持的运算符:

算数运算符:+ - ++ --

关系运算符:> < == !=

赋值运算符: =

算术运算符

#include <stdio.h>

int main(int argc, const char *argv[])
{

	//1.定义3个变量 分别是char short int 
	char v1 = 'a';
	short v2 = 100;
	int v3 = 200;

	//2.定义3个不同类型的指针
	char *p1 = &v1;
	short *p2 = &v2;
	int *p3 = &v3;

	//3.指针做加法运算:指针+数字
	printf("p1 = %p , P1 + 1 = %p\n",p1,p1+1);
	printf("p2 = %p , P2 + 1 = %p\n",p2,p2+1);
	printf("p3 = %p , P3 + 1 = %p\n",p3,p1+1);
/* 总结:指针类型第二个作用:指针+1 移动其指向类型大小的字节*/
	puts("------------------------------------------");
	
	//4.指针做减法运算:指针-数字
	printf("p1 = %p , P1 - 1 = %p\n",p1,p1-1);
	printf("p2 = %p , P2 - 1 = %p\n",p2,p2-1);
	printf("p3 = %p , P3 - 1 = %p\n",p3,p1-1);

	puts("------------------------------------------");

	//5.指针 - 指针。只有在连续空间中才有意义
	int arr[5] = {1,2,3,4,5};


	//获取数组里面每一个元素的地址
	for(int i = 0;i < 5;i++)
	{
		printf("arr[%d] = %p\n",i,&arr[i]);
	}

	printf("&arr[4] - &arr[0] = %ld\n",&arr[4]-&arr[0]);

	return 0;
}
结果:
p1 = 0x7ffe5f9c7fad , P1 + 1 = 0x7ffe5f9c7fae
p2 = 0x7ffe5f9c7fae , P2 + 1 = 0x7ffe5f9c7fb0
p3 = 0x7ffe5f9c7fb0 , P3 + 1 = 0x7ffe5f9c7fae
------------------------------------------
p1 = 0x7ffe5f9c7fad , P1 - 1 = 0x7ffe5f9c7fac
p2 = 0x7ffe5f9c7fae , P2 - 1 = 0x7ffe5f9c7fac
p3 = 0x7ffe5f9c7fb0 , P3 - 1 = 0x7ffe5f9c7fac
------------------------------------------
arr[0] = 0x7ffe5f9c7fd0
arr[1] = 0x7ffe5f9c7fd4
arr[2] = 0x7ffe5f9c7fd8
arr[3] = 0x7ffe5f9c7fdc
arr[4] = 0x7ffe5f9c7fe0
&arr[4] - &arr[0] = 4

比较运算符

指针的比较运算符:>  <  !=  ==
注意:
    指针的 > < : 只有在连续的空间才有意义;
    两个普通类型变量的地址之间没有大小关系(因为是操作系统随机分配的);
    指针 == 运算符;
        表示的是两个变量是否是同一个。

赋值运算

指针赋值运算
    本质:给指针赋值操作;
eg:
    int number = 10;
    int value = 20;

//定义一个指针
int *p = &number;//定义一个指针,里面初始化的值是number的地址

//赋值运算符可以改变指针的指向
p = &value; //将指针的指向 改为指向 value 的地址
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值