01. 作用域
局部变量:也是auto变量(auto可省略),定义在函数内部的变量
作用域:从定义开始,到包裹该变量的代码块结束
生命周期:从变量定义开始,到函数调用完成。——当前函数
全局变量:定义在函数外部的变量
作用域:从定义位置开始,默认到文件内部。其他文件如果想使用,可以通过extern关键字 声明全局变量 将作用域导出
生命周期:程序启动开始,到程序终止结束。——程序执行期间
static全局变量:在全局变量定义之前添加 static关键字
作用域:限制在本文件内部,不允许通过 extern关键字声明导出到其他文件
生命周期:程序启动开始,到程序终止结束。——程序执行期间
static局部变量:在局局变量定义之前添加 static关键字
特性:静态局部变量只定义一次,在全局内存中。通常用来做计数器
作用域:从定义开始,到包裹该变量的代码块结束
生命周期:程序启动开始,到程序终止结束。——程序执行期间
全局函数:类型 函数名(形参) + 函数体
作用域:整个程序
生命周期:程序启动开始,到程序终止结束。——程序执行期间
static函数:static 类型 函数名(形参) + 函数体
作用域:static函数只能在本文件内部使用。
生命周期:程序启动开始,到程序终止结束。——程序执行期间
#include <stdio.h>
int variate02;
static int svar02;
void fun01()
{
return;
}
static void fun02()
{
return;
}
int main()
{
auto int variate01 = 10;
static int svar01;
return 0;
}
02. 内存布局
由于Windows操作系统不开放源码,所以不清楚Windows平台下的内存怎么分布
Linux系统开发源码。所以可以看到内部实际存储
内存4区模型:
- 代码段:.text段。程序源代码(二进制形式)
- 数据段:
- 只读数据段 .rodata段,存放 常量
- 初始化数据段 .data段,存放 初始化为非0的全局变量和静态变量
- 未初始化数据段 .bss段,存放 未初始化的全局变量和静态变量,程序加载执行前,会将该段整体赋值为0
- stack:栈。空间小,系统自动管理、自动分配、自动释放。 特性是FILO(先进后出)。 Windows下默认是1M,可提升上限至10M。Linux下默认是8M,可提升上限至16M
- heap:堆。空间大,用户自己管理、分配、释放。特性是FIFO(先进先出)。约1.3G+
内存4区图如下(Linux版)
03. malloc()、free()
malloc()函数:堆区申请内存空间
#include <stdlib.h>
void *malloc(size_t size);
功能:在堆区内存中分配一块长度为size字节的连续区域,用来存放类型说明符指定的类型。
参数:需要分配内存大小(单位:字节)
返回值:
成功:分配空间的起始地址
失败:NULL
free()函数:释放空间
#include <stdlib.h>
void free(void *ptr);
功能:释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,指向被释放区域的首地址。对同一内存空间多次释放会出错。
参数:需要释放空间的首地址,被释放区应是由malloc函数所分配的区域。
返回值:无
malloc()、free()的使用:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = (int*)malloc(sizeof(int)*10);
if(p == NULL)
{
printf("malloc error\n");
return -1;
}
free(p);
p = NULL;
return 0;
}
使用heap空间注意事项:
- free后,空间不会失效。通常free后,地址置为NUK=LL
- free地址必须是 malloc申请地址,否则free时会出错。(如:不要p++)
- 如果malloc之后的地址需要变化,那么可以使用临时变量temp保存原地址,然后free(temp);
04. 存储类型操作函数
memset()
分配的内存空间内容不确定,一般使用memset初始化。
#include <string.h>
void *memset(void *s, int c, size_t n);
功能:将s的内存区域的前n个字节以参数c填入
参数:
参1:需要操作内存s的首地址
参2:填充的字符,c虽然参数为int,但必须是unsigned char , 范围为0~255
参3:指定需要设置的大小
返回值:s的首地址
memset()函数用法:
int a[10];
memset(a, 0, sizeof(a));
memset(a, 97, sizeof(a));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%c\n", a[i]);
}
memcpy()
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
功能:拷贝src所指的内存内容的前n个字节到dest所值的内存地址上。
参数:
参1:目的内存首地址
参2:源内存首地址,注意:dest和src所指的内存空间不可重叠
参3:需要拷贝的字节数
返回值:dest的首地址
memcpy()函数用法:
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int b[10];
memcpy(b, a, sizeof(a));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d, ", b[i]);
}
memmove()
memmove()功能用法和memcpy()一样,区别在于:dest和src所指的内存空间重叠时,memmove()仍然能处理,不过执行效率比memcpy()低些。
memcmp()
#include <string.h>
int memcmp(const void *s1, const void *s2, size_t n);
功能:比较s1和s2所指向内存区域的前n个字节
参数:
参1:内存首地址1
参2:内存首地址2
参3:需比较的前n个字节
返回值:
相等:=0
大于:>0
小于:<0
memcmp()函数用法:
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int b[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int flag = memcmp(a, b, sizeof(a));
printf("flag = %d\n", flag);
05. 就近原则
#include <stdio.h>
int m = 100;
int main()
{
int m = 10;
printf("m = %d\n",m);
return 0;
}
不建议自己这样写。只需要知道有这么个原理,别人这么写代码时看的懂,就够了。 of(a)); printf(“flag = %d\n”, flag);
# 05. 就近原则
```c
#include <stdio.h>
int m = 100;
int main()
{
int m = 10;
printf("m = %d\n",m); //10
//不建议这样写
return 0;
}
不建议自己这样写。只需要知道有这么个原理,别人这么写代码时看的懂,就够了。
|