c复习day08

作用域

  • 变量起作用的范围

变量

  • 局部变量:再{}范围之内定义的变量
  • auto int a;
  • 静态局部变量:再{}范围之内定义的变量,前面加上static修饰变量
  • static int a;
  • 全局变量:再函数之外定义的变量
  • 静态全局变量:再函数之外定义的变量,加上static修饰的变量
生命周期

什么时候开辟空间(出生),释放空间(死亡),这个过程叫生命周期

局部变量

  • 作用域 :在定义变量的{}之内有效
  • 生命周期:程序运行至变量定义处开辟空间,所在的函数结束之后释放空间
  • 未初始化的值:随机

静态局部变量

  • 作用域:在定义变量的{}之内有效
  • 生命周期:执行main函数之前就已经开辟空间,程序结束之后才释放空间
  • 未初始化的值:0

全局变量

  • 作用域:整个工程,所有文件
  • 生命周期:执行main函数之前就已经开辟空间,程序结束之后才释放空间
  • 未初始化的值:0

静态全局变量

  • 作用域:当前文件
  • 生命周期:执行main函数之前就已经开辟空间,程序结束之后才释放空间
  • 未初始化的值:0

变量小节

  • 作用域:局部变量(普通局部和静态局部)在{}范围之内,普通全局作用于整个工程,静态全局作用域当前文件
  • 生命周期:只有普通局部是运行至变量定义处时开辟,函数结束释放,其他变量都是执行main函数之前就已经开辟空间,在程序结束之后才释放空间
  • 初始化的值:只有普通局部变量未初始化的值为随机值,其他为0

注意:在.h中,全局变量只声名不定义,定义放在.c文件中

变量的重命名问题

  • 考虑作用域前提下,就近原则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
int num = 0;
void fun()
{
printf("%d\n",num);
}
//static int num = 20;
static void fun1()
{
printf("num = %d\n",num);
}
void fun2()
{
fun1();
}
//不同的作用域可以重名
int main()
{
fun();
fun2();
int num = 10;
printf("num1 = %d\n",num);
{
int num = 100;
}
printf("num2 = %d\n",num);
return 0;
}

静态函数

  • 静态函数就是在函数定义时加上static修饰的函数,静态函数只可以被当前文件函数调用
  • static void fun (){}
  • 普通的函数没有加任何修饰,就是全局函数,整个工程可以调用

程序内存分布

静态全局
  • 普通静态局部变量,全局变量,静态全局变量
内存从上到下分布
  • 栈区:存放局部普通变量
  • 堆区:使用时需要申请malloc
  • 静态全局区:分为未初始化的静态全局(bss)和初始化的静态全局(data)
  • 文字常量区
  • 代码区
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int e;
static int f;
int g = 10;
static h = 10;
int main()
{
int a;
int b = 10;
static int c;
static int d = 10;
char *i = "test";
char *k = NULL;
}

以上代码的内存分布

  • 栈区:a, b i , k
  • 静态全局区(未初始化):e , f , c
  • 静态全局区(已初始化):g, h ,d
  • 文字常量区:”test”

memset

1
2
3
4
5
6
7
8
#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的首地址
代码实列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
include<stdio.h>
#include<string.h>
int main()
{
int a = 10;
memset(&a,1,sizeof(a));
printf("%d\n",a);
char buf[10] = "";
strcpy(buf,"hello");
printf("%s\n",buf);
memset(buf,0,sizeof(buf));
printf("%s\n",buf);
//将前九个元素设置为a
memset(buf,'a',sizeof(buf)-1);
printf("%s\n",buf);
return 0;
}

memcpy内存拷贝

1
2
3
4
5
6
7
8
#include <string.h>
void *memcpy(void *dest,cost void *src,size_t n);
功能:拷贝src所指的内存内容的前n字节到dest所指的内存地址上
参数
dest:目的的内存地址
src:源内存的地址
n:徐娅拷贝的的字节数
返回值:dest的首地址
代码示例一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
char str1[128] = "";
char str2[128] = "abc\0def\0dadfa";
//memcpy(str1,str2,10*sizeof(char));
strncpy(str1, str2, 10 * sizeof(char));
for (int i = 0; i < 10; i++)
{
printf("%d ",str1[i]);

}
system("pause");
return 0;
}
代码示例二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <string.h>
#include <stdio.h>

int main()
{
int str1[10] = {1,2,3,4,5,6,7,8,9};
int str2[10] = {0};
//将str1中前五个元素拷贝到str2中
memcpy(str2,str1,sizeof(int)*5);
for (int i = 0; i < sizeof(str2)/sizeof(str2[0]); i++)
{
printf("%d\n",str2[i]);
}

return 0;
}

memcmp

1
2
3
4
5
6
7
8
9
10
11
12
#include <string.h>
int memcmp(const void *s1,const void *s2,size_t n);
功能:比较s1和s2所指向内存区域的前n个字节
参数:
s1:内存首地址1
s2:内存首地址2
n:需要比较的前n字节
返回值:
相等:=0
大于:>0
小于:<0

代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
#include<string.h>

int main()
{
char num1[] = {1,0,3,4,5,6,7};
char num2[] = {1,0,3,6,5,6,7};
char str1[] = "dbafs\0fdsa";
char str2[] = "dbafs\0gdsa";

// printf("%d\n",memcpy(str1,str2,sizeof(str1)));
// printf("%d\n",strncmp(str1,str2,sizeof(str1)));

printf("%d\n",memcmp(num1,num2,7*sizeof(num1)));
printf("%d\n",strncmp(num1,num2,7*sizeof(num1)));
return 0;
}


  • 总之:内存操作函数遇到\0和0都不会结束操作,而str字符函数都会结束

malloc 向堆区申请空间

1
2
3
4
5
6
7
8
#include <stdlib.h>
void * malloc(size_t size)
功能:在内存的动态存储区(堆区)中分配一块长度为size字节的连续区域用来存放类型说明符指定的 类型,分配的内存空间内容不确定,一般用memset来初始化
参数:
size:需要分配的内存大小(单位:字节)
返回值:
成功:分配空间的起始地址
失败:NULL

free

1
2
3
4
5
6
7
#incldue <stdlib.h>
void free(void *ptr);
功能:释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,指向被释放区域的首地址
:对同一块内存多次释放会出错
参数:
ptr:需要释放空间的首地址,被释放区应是由malloc函数所分配的区域
返回值:无

注意:free指定释放一次上次申请的空间

free 参数 地址必须是上一次malloc申请过的,不能改变这个地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<string.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
//申请一个字符数组,有1024字节
char *p = (char *)malloc(1024);
memset(p,0,1024);
// free(p+1);err
strcpy(p,"helloworld");
printf("%s\n",p);
free(p);
return 0;
}
测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main()
{
//申请一个数组,数组中有十个元素,每个元素为int类型
int *p = (int *)malloc(sizeof(int)*10);
memset(p,0,sizeof(int)*10);
*p = 1000;
*(p+5) = 2000;
for (size_t i = 0; i < 10; i++)
{
printf("%d\n",*(p+i));

}
return 0;
}
你的支持是我最大的动力!
0%