C语言基础 (10) 变量作用域,生命周期 内存结构

时间:2022-03-24 06:32:25

01 课程回顾

1.指针数组

注意: 对于数组来说,在使用sizeof的时候a和&a[0]是不一样的,

虽然以%x打印出来他们都是地址

2.值传递

int a;

fun(a);

int *****p;

fun(p); // 这个也是值传递,把p的值传过去了 所以是值传递,并没有取地址

3.栈区和字符常量区

a[i] 等价于 *(a+i)

4.局部变量的问题:

C语言基础 (10) 变量作用域,生命周期 内存结构

5.strcpy虽然第一个参数是指针,但是内部实现是像指针所指向的内存拷贝内容:

C语言基础 (10) 变量作用域,生命周期 内存结构

6.char *p1 = “hello mike”; 记住这种写法 p1是一个字符型指针 保存的是hello mike字符常量首元素地址

注意:sizeof(p1)是4!

3 字符串常量和字符指针数组

char *p1 = “abc”;

char tmp[100];

strcpy(tmp,p1)

// 不能改p1指向的内存 char const *p1

// p1指向文字常量区的指针变量

char p2[] = “abc”;

char p3[100];

strcpy(p3,”abc”);

// 可以改变数组元素

// 把abc拷贝到数组p2中

// p3=”abc”// err 数组名是常量

// 类比

char a,b,c;

// 指针数组,它是数组,每个元素都是指针,

// 每个元素都是int *,都是指向int

char *p[] = {&a,&b,&c};

char *str1 = “abc”;

char *str2 = “mike”;

char *str3 = “hello”;

//p3,它是数组,它保存了3个字符串的首元素地址

char *p2[] = {“abc”,”mike”,”hello”}

char *p2[3]

p2[0] = “abc”

p2[1] = “mike”

p2[3] = “hello”

04 普通局部变量

作用域:作用的范围

1 普通局部变量

2  static局部变量

3 普通全局变量

4  static全局变量

5 普通函数和static函数的区别

C语言基础 (10) 变量作用域,生命周期 内存结构

5 课堂答疑:二级指针和字符指针数组的区别

char *p3[] = {“abc”,”mike”,”hello“};

char **p3 = {“abc”,”mike”,”helo”}; //err

char *tmp

char **tmp = &tmp;//ok

//str首元素是什么类型? char *

//&str[0] 代表首元素地址 str等价于&str[0]

char *str[] = {“abc”,”mike”,”hello”};

char **p = str; // char ** 指向char*

char **p = &str[0]

fun(str)

// 如果char *str[]作为函数参数 可以改为char **str

vpod fun(char **p)

// 下面三者等价,编译器都是当作 char **p处理

void fun(char **p)

void fun(char *p[])

void fun(char *p[100])

void fun(int a[])

void fun(int a[100])

void fun(int *a);

结论:只要是形参中的数组都不是数组,而是指针。

6 static局部变量

// 1.static局部变量,是在编译阶段就已经分配空间,(函数没有调用前,已经存在)

// 2.当离开{ },static局部变量不会释放,只有程序结束,static变量才自动释放

// 3.如果static局部变量不初始化,它的值默认为0

(普通局部变量不初始化,它的值默认为随机数)

// 4.只有执行到34行才初始化,static局部变量初始化语句,只会执行一次,但是可以赋值多次

// 5.static变量只能用常量初始化(注意)

int a = 10;

//static int j = a;  // err,使用变量a给static变量初始化(会报错,因为这个东西是在编译阶段进行的,a还没有值

static放在data区

(左边是栈区

C语言基础 (10) 变量作用域,生命周期 内存结构

(在编译阶段就已经在data区存在了

06 普通局部变量和static局部变量区别:

1、  内存分配和释放

a)       普通局部变量只有执行到定义变量的语句才分配空间

b)       static局部变量在编译阶段(函数还没有执行),变量的空间已经分离

c)       普通局部变量离开作用域{},自动释放

d)       static局部变量只有在整个程序结束才自动释放

2、  初始化

a)       普通局部变量不初始化,值为随机数

b)       static局部变量不初始化,值为0

c)       static局部变量初始化语句只有第一次执行时有效

d)       static局部变量只能用常量初始化

8 普通全局变量

C语言基础 (10) 变量作用域,生命周期 内存结构

//8、不同文件,普通变量只能定义一次,可以声明多次

C语言基础 (10) 变量作用域,生命周期 内存结构

09 C语言全局变量的缺陷

声明和定义的区别:

DEFINITION = DECLARATION + SPACE RESERVATION

定义就是声明的同时申请了一段空间

C语言基础 (10) 变量作用域,生命周期 内存结构

C语言基础 (10) 变量作用域,生命周期 内存结构

(这样看比较迷 这就是这节课讲的C语言缺陷。)

10 C语言全局变量声明和定义的建议写法

C语言基础 (10) 变量作用域,生命周期 内存结构

11 全局变量分文件

C语言基础 (10) 变量作用域,生命周期 内存结构

(使用前应进行声明

当然这种方法不太方便,如果有多个文件都需要引用,建议使用头文件

12 思考题

13 全局变量分文件补充

复习一下,

防止头文件重复包含: 是指, 在同一个文件中,如果一个文件被包含多次,只有第一次有效

注意是指在一个文件中

C语言基础 (10) 变量作用域,生命周期 内存结构

14 static全局变量

a)       static全局变量和 普通全局变量的区别就是作用域不一样(文件作用域

b)       extern 关键字只适用于普通全局变量

c)       普通全局变量,所有文件都能使用,前提需要声明

d)       static全局变量只能本文件使用,别的文件不能使用

e)       不同文件只能出现一个普通全局变量的定义

f)        一个文件只能有一个static全局变量的定义,不同文件间的static全局变量,就算名字相同,也是没有关系的2个变量

C语言基础 (10) 变量作用域,生命周期 内存结构

static全局变量和普通全局变量的区别就是作用域不一样(文件作用域)

extern 关键字只适用于普通全局变量

1.  一个文件只能有一个static 全局变量的定义,一个文件不能出现多个

1.  static全局变量只能在当前文件使用

C语言基础 (10) 变量作用域,生命周期 内存结构

(这个图片中在右边的文件中定义了,在左边使用不了

15 作用域和生命周期总结

静态全局变量只能当前文件用

普通全局变量 所有都能用

如果不做初始化静态全局变量和普通全局变量都是0(局部变量如果不初始化就是随机的)

术语:

static全局变量 内部链接

普通全局变量 外部链接

普通函数和static函数的区别(文件作用域)

a)       所有文件只能有一次普通函数的定义

b)       一个文件可以有一个static函数的定义

a)       普通函数所有文件都能调用,前提是使用前声明

b)       static函数只能在定义所在的文件中使用

C语言基础 (10) 变量作用域,生命周期 内存结构

16 内存分区介绍

预处理:头文件展开 宏定义展开 条件编译

编译: 做语法检查,编译成汇编代码

生成目标代码 目标代码是不能执行的 (可以用linux的size命令查看

链接,生成可执行程序

C语言基础 (10) 变量作用域,生命周期 内存结构

text:代码区

data:data区

在程序没有执行前,有几个内存分区已经确定 (已确定不代表已加载内存 只是已经确定

程序只有运行时才会加载到内存:

text(代码区): 只读,函数

data: 初始化数据,全局变量,static变量(全局 局部, 文字常量区(只读

bss: 没有初始化的数据,  全局变量,static变量(全局 局部, 文字常量区(只读

stack(栈区): 普通局部变量,自动管理内存(自动分配空间,自动释放) 运行的时候才有  先进后出的特点

heap(堆区): 手动申请空间,手动释放,整个程序结束,系统也会自动回收。如果程序没结束,没有手动释放,这个堆区空间不会自动释放

当运行程序,加载内存,首先根据前面确定的内存分区(text,data,bss)先加载 然后额外加载两个区(栈区,堆区

总结一下:text(代码区 主要存的是函数代码 data区.bss区存的是全局..文字常量..

栈区、堆区

C语言基础 (10) 变量作用域,生命周期 内存结构

进程内存结构

栈从上向下,堆从下向上

C语言基础 (10) 变量作用域,生命周期 内存结构

进程的内存layout  一个进程操作着他自己的虚拟地址空间,区别于其他进程的虚拟地址空

17 栈越界说明

ulimit

C语言基础 (10) 变量作用域,生命周期 内存结构

C语言基础 (10) 变量作用域,生命周期 内存结构

C语言基础 (10) 变量作用域,生命周期 内存结构

18 memset的使用

其实堆区会比栈区大一点儿

strpy()

strncpy()

strcmp()

功能:将s的内存区域的前n个字节以参数c填入

C语言基础 (10) 变量作用域,生命周期 内存结构

C语言基础 (10) 变量作用域,生命周期 内存结构

19 memset使用补充

C语言基础 (10) 变量作用域,生命周期 内存结构

20 memcpy的使用

C语言基础 (10) 变量作用域,生命周期 内存结构

21 memmove和 memcmp 的使用

C语言基础 (10) 变量作用域,生命周期 内存结构

C语言基础 (10) 变量作用域,生命周期 内存结构

(只要有一个比你大我就大,比ascii码

22 指针指向栈区空间

C语言基础 (10) 变量作用域,生命周期 内存结构

23 指针指向堆空间

C语言基础 (10) 变量作用域,生命周期 内存结构

C语言基础 (10) 变量作用域,生命周期 内存结构

24 堆空间使用总结

C语言基础 (10) 变量作用域,生命周期 内存结构

内存泄漏:动态分配了空间,不释放

C语言基础 (10) 变量作用域,生命周期 内存结构

内存污染: 非法使用内存

25 释放说明:

C语言基础 (10) 变量作用域,生命周期 内存结构

calloc (就业班

realloc (就业班

26 堆区空间越界

C语言基础 (10) 变量作用域,生命周期 内存结构

27 作业