zoukankan      html  css  js  c++  java
  • C语言基础 (10) 变量作用域,生命周期 内存结构

    01 课程回顾

    1.指针数组

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

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

    2.值传递

    int a;

    fun(a);

    int *****p;

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

    3.栈区和字符常量区

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

     

     

    4.局部变量的问题:

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

    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函数的区别

     

    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区

    (左边是栈区

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

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

    1、  内存分配和释放

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

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

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

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

    2、  初始化

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

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

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

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

    8 普通全局变量

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

    09 C语言全局变量的缺陷

    声明和定义的区别:

    DEFINITION = DECLARATION + SPACE RESERVATION

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

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

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

    11 全局变量分文件

    (使用前应进行声明

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

    12 思考题

    13 全局变量分文件补充

    复习一下,

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

    注意是指在一个文件中

    14 static全局变量

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

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

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

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

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

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

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

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

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

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

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

    15 作用域和生命周期总结

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

    普通全局变量 所有都能用

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

    术语:

    static全局变量 内部链接

    普通全局变量 外部链接

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

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

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

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

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

    16 内存分区介绍

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

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

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

    链接,生成可执行程序

    text:代码区

    data:data区

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

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

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

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

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

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

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

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

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

    栈区、堆区

    进程内存结构

    栈从上向下,堆从下向上

     

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

    17 栈越界说明

    ulimit

    18 memset的使用

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

    strpy()

    strncpy()

    strcmp()

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

    19 memset使用补充

    20 memcpy的使用

    21 memmove和 memcmp 的使用

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

    22 指针指向栈区空间

    23 指针指向堆空间

     

     

    24 堆空间使用总结

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

    内存污染: 非法使用内存

    25 释放说明:

    calloc (就业班

    realloc (就业班

    26 堆区空间越界

    27 作业

  • 相关阅读:
    提高写作能力
    成长,潜力
    线性代数
    健康的作息时间
    2021-01-06TX技术经验总结.
    Redis的技术总结
    Rocket MQ 原理.
    MBA
    向上管理
    postman怎么打开console控制台,打印console.log
  • 原文地址:https://www.cnblogs.com/eret9616/p/10223037.html
Copyright © 2011-2022 走看看