作用域:
局部变量:在函数内部定义的变量称为局部变量(auto),作用域为局部变量创建到函数结束;
全局变量:在函数外部定义的变量,作用于整个程序;
如果在代码中全局变量与局部变量有相同变量名,局部变量覆盖全局变量;
static:如果没初始化默认设置的值为0
静态局部变量:程序创建之初定义,只能在程序创建时被初始化一次,作用域 为函数内部;
静态全局变量:程序创建之初定义,只能在程序创建时被初始化一次,作用域缩小为只在本文件有效;
全局函数:在程序中声明的函数默认为全局函数,作用于整个项目;
静态函数:加static修饰,作用域缩小为只在本文件有效,如果和全局函数重名那么在该文件中使用static修饰的函数;
内存布局
内存可执行程序四区模型
代码区:
存放计算机程序指令
只读,共享
|
数据区:
1.字符串常量 char* s = "hello";
2.初始化数据区:
全局变量,全局常量,static修饰的全局,局部变量
3.未初始化数据区:(bss段)
全局变量,全局常量,static修饰的全局,局部变量
|
栈区:
在程序加载到内存中,系统自动分配给每个程序一定的空间(一般情况windos下一般为1-8M,linux下一般为1-16M)用来存储数据,当程序执行完成,系统自动回收
存放:局部变量,const修饰的常量(必须是局部变量),指针,结构体,联合体,枚举,函数的形参
|
堆区:
由程序员自己分配和释放的空间。
堆空间开辟
malloc / calloc / realloc
释放
free
|
内存模型
合称数据区
代码区 | data区 | bss区 |
堆区
| 栈区 |
开辟二级指针空间
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main()
{
//先开辟外层空间存储一级指针
int **p = (int**)malloc(sizeof(int*)* 3);
for(int i = 0; i < 3;i++)
{
//开辟一级指针存变量地址
p[i] = (int*)malloc(sizeof(int*)*3);
}
for(int i = 0; i < 3;i++)
{
int sum = 0;
for(int j = 0; j < 3; j++)
{
scanf("%d",&p[i][j]);
sum += p[i][j];
}
printf("总成绩 %d\n",sum);
}
//释放内存空间
for(int i = 0; i < 3;i++)
{
free(p[i]);//先释放内层
p[i] = NULL;
}
free(p);//再释放外层
p = NULL;
system("pause");
return 0;
}
memset
#include
<string.h>
void
*
memset
(
void
*
s
地址
,
int
c
,
size_t
n
);
功能:将s的内存区域的前n个字节以参数c填入
参数:
s:需要操作内存s的首地址
c:填充的字符,c虽然参数为int,但必须是
unsigned char , 范围为0~255
n:指定需要设置的大小
返回值:s的首地址
strcpy(操作的字符串)
#include
<string.h>
char
*
strcpy
(
char
*
dest
,
const
char
*
src
);
功能:把src所指向的字符串复制到dest所指向的空间中,
'\0'也会拷贝过去
参数:
dest:目的字符串首地址
src:源字符首地址
返回值:
成功:返回dest字符串的首地址
失败:NULL
注意:
如果参数dest所指的内存空间不够大,可能会造成缓冲溢出的错误
strncpy
#include
<string.h>
char
*
strncpy
(
char
*
dest
,
const
char
*
src
,
size_t
n
);
功能:把src指向字符串的前n个字符复制到dest所指向的空间中,
是否拷贝结束符看指定的长度是否包含
'\0'。
参数:
dest:目的字符串首地址
src:源字符首地址
n:指定需要拷贝字符串个数
返回值:
成功:返回dest字符串的首地址
失败:NULL
memcpy(操作的一块内存空间以字节为单位)
#include
<string.h>
void
*
memcpy
(
void
*
dest
,
const
void
*
src
,
size_t
n
);
功能:拷贝src所指的内存内容的前n个字节到dest所指的内存地址上。
参数:
dest:目的内存首地址
src:源内存首地址,
注意:dest和src所指的内存空间不可重叠
n:需要拷贝的字节数
返回值:dest的首地址
注意:当拷贝源和目标发生冲突时会可能会拷贝失败
memmove:相比memcpy更安全
memmove()功能用法和memcpy()一样,区别在于:dest和src所指的内存空间重叠时,memmove()仍然能处理,不过执行效率比memcpy()低些(如果
dest和src 内存
有冲突memmove会去开辟一个临时的空间,存储src所指的内存空间 的内容
)。
|
memcmp
#include
<string.h>
int
memcmp
(
const
void
*
s1
,
const
void
*
s2
,
size_t
n
);
功能:比较s1和s2所指向内存区域的前n个字节
参数: 返回值:
s1:内存首地址1 相等:=0
s2:内存首地址2 大于:>0
n:需比较的前n个字节 小于:<0
开辟堆空间易错点
char* s = NULL;
s = (char*)malloc(sizeof(char)*10);
//堆区
s = "hello";
//此时s被修改到了字符串常量区了
printf("%p",s);
free(s);
//此时找不到s的地址,会报错
开辟堆空间大小易错点
1、
int main()
{
int* p = (int*)malloc(0);//开辟0个空间大小 程序不会报错 但是个野指针
*P = 100;//操作野指针 可能会报错
free(p);
}
2、
int main()
{
int* p = (int*)malloc(2);//申请2个字节
*P = 100;//操作4个字节
free(p);
//操作额外空间会出错
}