嵌入式C语言-指针

3-指针

概述

C语言中的地址用point去描述

指针是内存类型资源地址、门牌号的代名词

指针 -> 就是地址的代名词

指针变量 -> 存放指针这个东西的盒子

int a;
*p

C语言编译器对指针这个特殊的概念,有2个疑问

1、分配一个空间,空间要多大?

在32位系统中,这个指针就4个字节(要涵盖2^32个地址,取决于系统的位数) <- 目的是存放地址

指针的大小sizeof是固定的

2、空间里存放的地址 所指向 内存的读取方法是什么?

读取方法取决于前面定义的数据类型,即指针读取包括首地址和要读的大小(大小取决于数据类型)

指针的变量有**首地址**和**读取长度**两个重要属性

指针指向内存空间,一定要保证合法性

指针修饰符

const

常量修饰 -> 只读【不能变】

const char *p;
char const *p;
char *const p;
char *p const;

其中 char constconst char 等价

其中 char * const pchar *p const 等价

推荐使用 const char *pchar *const p分别表示常量指针和指针常量

常量指针

const char *p 表示常量指针,即指向常量的指针,内容不允许修改,指针可以修改,往往用在字符串

const char *p = "hello world"

指针常量

char * const p 表示指针常量,即指针是一个常量,永远指向一个地址,不允许修改这个地址,往往用于表示硬件资源

const char * const p 地址和内容均是常量

volatile

防止优化指向内存地址,开关编译器优化的修饰符

防止软件优化掉,往往用于外界硬件控制信号的变量

volatile char *p

typedef

起别名xxx_t

char *name_t		name_t是一个指针,指向了一个char类型的内存
typedef char *name_t	name_t是一个指针类型的名称,指向了一个

这样我们直接使用name_t来定义这个指针

指针与运算符

指针基本运算

int *p = xxx

p+1 => [p] + 1 * sizeof(*p)

指针+1是向下移动一个单位,指针的加法运算,实际上加的是一个单位,单位的大小可以使用sizeof得到

p++ 就是自增 p = p + 1

指针标签访问[]

变量名[n] == *(变量名 + n}

地址内容的标签访问

char *p *(p+2) == p[2]

使用[]获取的是指针下的内容,使用p+n获取的是地址

强制类型转换

#include <stdio.h>

int main(){
	int a = 0x12345678;
	int b = 0x99999999;

	int *p1 = &b;

	char *p2 = (char *)&b;

	return 0;
}

多级指针

指向指针指针

int **p

通过多级指针可以实现逻辑上的连续存储!

多维指针的结束可以通过NULL来判断

argv[i] == NULL 表示结束了

数组

指针变量的特殊化 -> 数组

数组是内存分配的一种形式

定义一个空间:

1、大小

2、读取方式

数组的定义必须有一个数组名

数据类型 数组名[m]

m就是数组的大小,m的作用域是在申请的时候

int a[100];

初始化

空间的赋值

按照标签**逐一处理**

int a[10];

a[0] = xx;

a[1] = xx;

初始化赋值即在空间定义时,就告知编译器的初始化情况,空间的第一次赋值,初始化操作。

数组空间的初始化 和 变量的初始化 本质不同

字符串拷贝推荐使用 strncpy()strcpy()会导致内存泄露

内存拷贝 memcpy() 注意尺寸要乘以sizeof

int buf[10];
int sensor_buf[100];

memcpy(buf, sensor_buf, 10 * sizeof(int));

结构体字节对齐

使用对齐,牺牲一点空间间接换取时间的效率,常见4字节对齐

#include <stdio.h>
struct abc{
	char a;
	short e;
	int b;
};

struct my{
	char a;
	int b;
	short e;
};

int main(){
	struct abc buf;
	struct my buf1;
	printf("the buf is %lu, the buf1 is %lu\n", sizeof(buf), sizeof(buf1));
	return 0;

}

打包顺序导致字节对齐形式不同,两个struct的sizeof不同

最终结构体大小一定是4的倍数

内存

内存的属性:

1、大小

2、在哪里

我们定义一个变量的时候,要不断去思考这两个问题

查看地址尽量使用%p

标签就是地址,例如 main 标签

C语言内存空间由低到高分配如下

空间作用
内核空间应用程序不许访问
栈空间局部变量
运行时的堆空间malloc
全局数据空间初始化的data,未初始化的bss
static
只读数据段const
代码段code

使用

size xxx 可以看空间分配情况

nm 指令可以更详细看

栈空间

临时存储函数里定义的变量

局部变量 可读可写

函数内部的变量,函数一旦返回,就释放内存

堆空间

运行时分配到的空间,往往使用malloc动态分配

运行时可以自我管理分配和释放的空间,称之为堆空间,生存周期由程序员来决定

分配:

malloc() 一旦成功,返回分配好的地址

*p
p = malloc()

对于这个新地址的读法,由程序员灵活把握,输入参数指定分配的大小,单位就是B(字节)

char *p;
p = (char *)malloc(sizeof(char));

if(p == NULL){
	'''error'''
}

释放:

使用malloc分配的空间,一定注意使用 free() 进行释放,如果在函数中定义的,当函数结束后,很难释放,切记成对成域使用

free(p);
char *p;
p = (char *)malloc(sizeof(char));
if(!p){
	return -1;
}

free(p);

只读空间

只读空间包括:全局数据空间、只读数据段、代码段

代码段是只读的,会进行保护,若尝试在执行中修改代码段,会报段错误 Segmentation fault

静态控件,整个程序结束,释放内存
or’‘’
}



释放:

使用malloc分配的空间,一定注意使用 `free()` 进行释放,如果在函数中定义的,当函数结束后,很难释放,切记成对成域使用

```c
free(p);
char *p;
p = (char *)malloc(sizeof(char));
if(!p){
	return -1;
}

free(p);

只读空间

只读空间包括:全局数据空间、只读数据段、代码段

代码段是只读的,会进行保护,若尝试在执行中修改代码段,会报段错误 Segmentation fault

静态控件,整个程序结束,释放内存

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

圆圈圆圆圆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值