修饰变量的关键字
修饰变量的关键字+数据类型+变量名
auto:自动默认不写
register:
register是作为寄存器的变量,就是在CPU里面存储的地方
作用:
将频繁进行IO操作的变量声明成寄存器变量,节省数据读取操作的时间,提高执行效率。
register int i;
for(i=1;i<100000;i++)
{
printf("%d",i);
}
注意:
寄存器的数量有限,当寄存器用完时,即使声明了变量也会被看做普通变量。
当编译器检测到频繁的IO操作,且寄存区有空闲,会自动将变量提升为寄存器变量。
static:
作用:
一、修饰局部变量
1、修饰局部变量时,只会初始化局部变量一次。
2、在函数结束时static局部变量的空间不会被销毁。
3、依旧只能在在定义的函数中使用。
二、修饰全局变量
1、只能在当前文件(模块)中使用。
2、普通的全局变量分模块的时候,要想在别的模块中使用,可以使用extern声明:extern 数据类型 变量名;
3、static全局变量分模块的时候,不能在别的模块中使用,只能在当前文件使用。
三、修饰函数
static全局变量只能在当前文件(模块)中使用。
例子:
void test(void)
{
static int a = 1;
printf("%d\r\n",a);
a++;
}
int main()
{
test();
test(); //第二次运行,遇到静态变量初始化忽略这条语句
return 0;
}
场景:
流水灯
void flash(void)
{
static int n = 1;
printf("%d灯亮\r\n",n);
n++;
if(n>5)
{
n = 1;
}
}
int main()
{
while(1)
{
flash();
//延迟
sleep(0.5);
}
}
const:
作用:
只读的意思,修饰的空间内只能读不能写。且修饰的变量必须初始化。
区分:
1、const int *p;
const在*前面修饰*p,不能通过p修改其所指向的const int的值(如*p=20)。
但是可以修改常量指针p的指向(如p=&b)。
const int *p; //const在*前面修饰*p,不能通过*p修饰指向空间的数据。但p本身是可修改的。
#include <stdio.h>
int main() {
const int a = 5;
const int b = 10;
const int *p = &a; // p 指向 a
// 尝试通过 p 修改它所指向的整数值(这是不允许的)
// *p = 20; // 编译错误:不能通过 p 修改它所指向的 const int 值
// 但是 p 本身的值(即它指向的地址)是可以被修改的
p = &b; // 现在 p 指向 b
// 读取 p 指向的值
printf("%d\n", *p); // 输出:10
return 0;
}
2、int *const p = &a;
const在*后面修饰的是p,指针指向不能变量。要立刻给地址。
但是可以通过p修改它指向的整数值(如*p=10)。
int *const p = &a; //const在*后面修饰的是p,指针指向不能变量。要立刻给地址,否则后面用不了
#include <stdio.h>
int main()
{
int a = 5;
int *const p = &a; // p 是一个指向 int 的常量指针,指向 a
// 尝试修改 p 指向的地址(这是不允许的)
// int b = 10;
// p = &b; // 编译错误:p 是常量指针,不能改变其指向
// 通过 p 修改它所指向的整数值(这是允许的)
*p = 10; // 现在 a 的值被修改为 10
printf("%d\n", a); // 输出:10
return 0;
}
3、const int * const p = &a;
p和*p只读的。
不能通过p修改它指向的const int的值。
也不能通过常量指针p改变指向。
const int * const p = &a;// p和*p只读的。
#include <stdio.h>
int main() {
int a = 5;
const int * const p = &a; // p 是一个指向 const int 的常量指针,指向 a
// 尝试通过 p 修改它所指向的整数值(这是不允许的)
// *p = 10; // 编译错误:不能通过 p 修改它所指向的 const int 值
// 尝试改变 p 指向的地址(这也是不允许的)
// int b = 10;
// p = &b; // 编译错误:p 是常量指针,不能改变其指向
// 但你可以读取 p 指向的值
printf("%d\n", *p); // 输出:5
return 0;
}
const int a = 10; //写操作会报错
int const a = 10; //和上书定义时一样的,没有区别。
面试题:
const int *p和int const *p ---> 没有区别。
面试题2:
区分:const修饰哪一个空间,哪一个空间是只读的
volatile:
作用:
1、内存访问,编译器可以直接从内存中读取volatile修饰变量的值。
2、组织编译器优化,修饰的变量会被改变,使程序可以读到新的值。
#include<stdio.h>
// 延迟函数
void delay(void)
{
volatile int i,j;
for(i=0;i<100000;i++)
{
for(j=0;j<100000;j++)
{
}
}
}
int main(void)
{
printf("hello");
delay();
printf("world");
return 0;
}
extern:
用于声明外部变量,也可以作为函数的声明。
2、动态内存申请
作用:
需要空间的时候申请,使用完可以将空间释放。
mallloc:
申请空间的函数
#include <stdlib.h>
void *malloc(size_t size);
功能:
在堆区申请size个字节大小的空间,将首地址返回。
且malloc申请的空间没有类型,要用地址承接且用强转符保持等号两边类型一致。
如int *p=(int *)malloc(sizeof(int));
释放空间:
free(指针名); // 指针指向的空间
p = NULL; //为了避免野指针
注意:
单片机内如果没有内存管理模块(MMU),则不能用动态内存申请。