1.栈与堆的区别
栈的内存区域只有默认1M
项目设置--连接器,系统,设置默认栈的大小
2.内存四大区域
常量字符串在代码区
char *p = "tasklist";//赋值地址
//p是一个栈上的指针变量,存储了代码区常量字符串的地址
printf("%d,%d", sizeof(p), sizeof("tasklist"));
printf("%p", p);
printf("\n%p", &p);
*p = 'x';//代码区只能读,不可以写
3.全局变量
全局变量与函数一样,有声明与定义,声明可以多个,定义只有一个。
局部变量没有声明与定义的差别
全局变量就有声明与定义的差别,int a没有赋值,视为声明,赋值视作定义
全局变量与函数一样,声明可以多个,定义仅有一个
全局变量如果有声明,没有定义,会自动初始化一个为0
头文件尽量存放声明,存放定义包含多次,就会触发重定义
全局变量可以跨文件使用
默认的函数都是全局函数
同一个工程,不同源文件,不能出现两个同名的全局变量定义
4.静态区,堆区,栈区对比
作用域非常大,生存期与程序共存放,内存不会被回收
静态区与程序共存亡,内存不会被回收再次利用,除非程序消亡
栈区,块语句执行完成,消亡
堆区,自己free也会消亡,
Staitc 限定全局变量,函数作用域局限在当前文件。默认全局变量,函数,都是一个工程所有原码共享。
Static,局部变量,每次仅仅初始化一次。用于软件工程避免全局变量被意外修改。
static const int num = 100;//限制只能被当前的源文件所引用
静态全局变量,有const意味着是常量
extern声明一个外部变量,没有定义报错
int num1 = 10;
int num2 = 20;//栈区
void *p1 = malloc(1000);//p1在栈区,存储了堆区的地址
void *p2 = malloc(1000);
printf("%p,%p", &num1, &num2);
printf("\n%p,%p", &p1, &p2);//在堆区,存储了指针变量的地址
printf("\n%p,%p", p1, p2);//在栈区,存储了堆区的地址
5.堆栈增长方向
栈顶由高地址到低地址方向增长
存储非静态变量、函数参数、返回地址
6.线程技术
#include <windows.h>
#include <process.h> //进程的头文件
void runmsg(void *p)
{
MessageBoxA(0, "hello china", "hello world", 0);
}
void main()
{
_beginthread(runmsg, 0, NULL);//开启一个线程
_beginthread(runmsg, 0, NULL);
_beginthread(runmsg, 0, NULL);
getchar();
}
7.位字段的概念与用途
结构体加上整数,限定长度,节约内存
嵌入式开发必须节约内存,需要位域
struct MyStruct
{
unsigned char num:1;//限定只有一位,限定内存,节约内存
unsigned char data : 1;
};
位域,不能越界,溢出
位字段输出二进制数据
位字段可以把二进制数据处理为char进行简洁的处理
typedef struct
{
unsigned char ch1:1;
unsigned char ch2:1;
unsigned char ch3:1;
unsigned char ch4:1;
unsigned char ch5:1;
unsigned char ch6:1;
unsigned char ch7:1;
unsigned char ch8:1;
}bit;
void main()
{
printf("%d", sizeof(bit));//位字段的方式输出整数的二进制码
int num;
scanf("%d", &num);
bit *p = #
for (int i = 3; i >= 0;i--)
{
printf("%d%d%d%d %d%d%d%d ",
p[i].ch8,
p[i].ch7,
p[i].ch6,
p[i].ch5,
p[i].ch4,
p[i].ch3,
p[i].ch2,
p[i].ch1
);
}
system("pause");
}
字节分布:变量在内存,低字节低位,倒序排列
8.寄存器变量,寄存器变量不可以取地址
VC++会自动优化,不需要增加寄存器标识
GCC会实现寄存器优化
9.函数返回值副本机制
作为函数,不可以返回指向栈上的指针
返回值有副本机制,一般在寄存器
int jia(int a, int b)
{
int c = a + b;//栈上,
printf("\n%p", &c);
return c;//return有副本机制
}
void main()
{
int res = jia(12, 19);
//int *p = &(jia(1, 2));
//返回值有副本机制,一般在寄存器,
printf("\n\n\n");
printf("%d", res);
}
9.函数返回地址特点
int * add(int a, int b)
{
int c = a + b;
return &c;
}
//作为函数,不可以返回指向栈上的指针
int * addm(int a, int b)
{
int *p = (int *)malloc(4);
*p = a + b;
return p;
}
//作为函数,但是可以返回指向堆上的指针
void mainA()
{
int *p = addm(3, 9);
//printf("\n\n");
printf("%d", *p);
}