C语言之存储类、作用域、生命周期、链接属性

news2024/12/24 22:06:48

一 :概念解析

        1: 存储类       

        (1)存储类就是存储类型,就是描述C语言变量存储在什么地方

        (2)内存有多种管理方法:栈、堆数据段、bss段、.text段......一个变量的存储类属性就是描述这个变量存储在何种内存段中

        (3)譬如:局部变量分配在栈上,所以它的存储类就是栈;显示初始化为非0的全局变量被分配在数据段,显示初始化为0或为显示初始化(默认为0)分配在bss段

        2:作用域         

        (1)作用域就是这个变量起作用的范围

        (2)基本来说,C语言变量的作用域规则是代码块作用域。意思就是这个变量起作用的范围是当前的代码块。代码块就是一对大括号{}括起来的范围,所以一个变量的作用域是:这个变量定义所在的{}范围内从这个变量定义开始往后的部分

        3:生命周期

        (1)生命周期是描述这个变量什么时候诞生(运行时分配内存空间给这个变量)及什么时候死亡(运行时回收这个内存空间,此后不能访问这个内存地址,或者访问这个地址已经和这个变量无关了)

        (2)研究变量的生命周期可以让我们理解程序运行时的一些现象、理解C语言的一些规则       

       4:链接属性               

                

        (1)程序从源代码到最终可执行程序,经历的过程:编译、链接

        (2)编译阶段就是把源代码变成.o目标文件,目标文件里面有很多的符号和代码段、数据段、bss段等分段。符号就是编程中的变量名函数名等

        (3).O的目标文件链接生成最终可执行程序的时候,其实就是把符号和相对应的段给链接起来

      

C语言的符号有三种链接属性:外链接、内链接、无链接

二:linux操作系统系统下c程序的内存映像

        1:代码段、只读数据段

                (1)对应着程序中的代码(函数),代码段在linux中又叫文本段(.text)

                (2)只读数据段就是在程序运行时只能读不能写的数据,const修饰的常量有可能是存放在只读数据段的(但是不一定,const常量在不同平台实现方法不一定)

        2:数据段、bss段

                (1)数据段存:显示输出化为非零的全局变量;显示初始化为非零的static局部变量

                (2)bss段:显示初始化为0或未显示初始化的全局变量;显示初始化为0或未初始化的static局部变量

        3:堆

                (1)C语言中什么变量存储在堆内存中?C语言不会自动将变量存放到堆内存中,这是需要程序员自己根据需求进行申请堆内存放和释放堆内存

        4:文件映射区

                (1)内存映射区就是进程打开文件后,将这个文件的内容从硬盘读到进程的文件映射区,以后就直接在内存中操作这个这个文件,读完后在保存时再将内存中的文件写入到硬盘中去

                     

        5:栈

                   (1)栈内存区,局部变量分配在栈上,函数调用传参时也会用到栈     

       

        6:内核映射区

                   (1)内核映射区就是将操作系统内核程序映射到这个区域了

                   (2)对于linux中的每一个进程来说,它都以为整个系统中只有内核和它自己。它认为内存地址0xc0000000以下都是它自己的活动空间

                   (3)每一个进程都活在自己的独立进程空间内0~3G每一个进程是不同的(因为用了虚拟地址技术),但是内核是唯一的

        7:os下裸机下c程序加载执行的差异

                (1)C语言程序运行时环境有一定的要求,意思是单独个人写的C语言程序没法直接在内存中运行,需要外部协助,这段协助的代码叫加载运行代码(或者叫构建c运行时环境的代码,这一段代码在操作系统下是别人写好的),这段代码的主要作用是:给全局变量赋值、清bss段

                (2)在裸机程序中没人来帮我们做加载运行时的代码,要程序员自己来做;而在操作系统下运行程序 时不用操心会自动重定位和清bss段

                (3)数据段的全局变量和静态局部变量都是有非零的初值的,这些初值在main函数运行之前就已经被初始化了,是重定位期间完成的初始化

三:存储类相关的关键字

        1:auto

                (1)auto关键字只有一个作用,修饰局部变量

                (2)auto修饰局部变量,表示这个局部变量是自动局部变量,自动局部变量分配在栈上。(分配在栈上,说明不初始化的话那么 它的值就是随机的)

                (3)平时定义的局部变量其实就是auto的,只是省略了关键字,auto的局部变量其实就是默认定义的普通的局部变量

        2:static

                (1)staticC语言中有两种用法,并且这两张用法之间彼此是毫无关联的、完全是独立的

                (2)第一种用法:用来修饰局部变量 ,形成静态局部变量。静态局部变量和非静态局部变量的区别:本质区别是存储类不同,非静态局部变量(普通局部变量)分配在栈上,而静态局部变量分配在数据段/bss段(初始化了分配在数据段,未初始化或初始化为0分配在bss段)

                (3)第二种用法:用来修饰全局变量,形成静态全局变量。静态全局变量和非静态全局变量的区别:链接属性不同

                分析:

                        1:静态局部变量在存储类方面和全局变量一样

                        2:静态局部变量的生命周期和全局变量一样

                        3:静态局部变量和 全局变量的区别:作用域和链接属性不一样

                                静态局部变量的是代码块作用域(和普通局部变量是一样的) ,链接属性是无链接

                                全局变量作用域是文件作用域(和函数是一样的)、链接是无链接

                                       

        3:register

                (1)register修饰的变量编译器会尽量将它分配在寄存器中(平时一般的变量都是分配在内存中。)分配在寄存器中一样的能用,但是读写效率会高很多。当一个变量需要反复被使用时,那么就可以用register关键字来修饰,通过改善这个变量的访问效率可以可以极大的提示程序的运行效率,所以register是一种极致提示程序运行效率的方式

                (2)用register关键字修饰变量编译器只能保证尽量放在寄存器中,不保证一定放在寄存器中。主要是因为寄存器的数量是有限的,编译器会考虑寄存器的数量够不够用来决定

        4:extern

                (1)extern关键字主要用来声明全局变量,声明的主要目的是为了在4.7.4.extern1.c文件中定义了全局变量,但是在4.7.4.extern.c这个文件中要调用这个变量

        

//4.7.4.extern.c 文件中的内容

#include <stdio.h>

int main(void)
{

    printf("g_c = %d\n",g_c);


    return 0;
    
}

//4.7.4.extern1.c 文件里的内容

int g_c = 4;

 使用 gcc 4.7.4.extern.c 4.7.4.extern1.c -o ab 命令编译链接生成可执行文件

 报错:

4.7.4.extern.c: In function ‘main’:
4.7.4.extern.c:6:25: error: ‘g_c’ undeclared (first use in this function)
    6 |     printf("g_c = %d\n",g_c);
      |                         ^~~
4.7.4.extern.c:6:25: note: each undeclared identifier is reported only once for each function it appears in

报错显示说g_c在 4.7.4.extern.c 这个文件中未声明

                (2)C语言中程序的编译是以单这就文件为单位的,因此编译 4.7.4.extern.c 源文件时只会考虑 4.7.4.extern.c 文件内的内容(不会考虑 4.7.4.extern1.c里面的内容),这就导致了程序员在a.c中调用b.c这个文件的时候在编译时会出现错误,解决方法就是声明它

                (3)应该在 4.7.4.extern.c中使用g_c这个变量时先声明它,,声明就是告诉a.c在别的文件中定义了g_c,并且它的原型和在a.c中声明的一样,将来链接的时候会在别的 .o文件中找到这个同名变量

#include <stdio.h>
 
extern int g_c;  //这里不能进行初始化
int main(void)
{

    printf("g_c = %d\n",g_c);


    return 0;

}
int g_c = 4;

使用 gcc 4.7.4.extern.c 4.7.4.extern1.c -o ab 命令编译链接生成可执行文件

运行结果:

        5:volatile

                (1)voiatile的字面意思:可变的、易变的。C语言中的volatile用来修饰一个变量,表示这个变量可以被编译器之外的东西改变。编译器之内的意思是变量的值的改变是代码的作用,编译器之外的改变就是这个改变不是代码造成的

,或者不是当前的代码造成的,编译器在编译当前代码时无法预知。譬如在中断处理程序isr中改变了这个变量的值,或者在多线程在别的线程更改了这个变量的值,或者硬件自动更改了这个变量的值(一般这个变量是寄存器的值)

                (2)以上说的三种情况,(中断isr中引用的变量,多线程中共用的变量,硬件会更改的变量)都是编译器在编译时无法预知的更改,此时应该使用volatile告诉编译器这个变量属于这种(可变的、易变的)情况。  编译器遇到volatile修饰的变量时就不会对改变量的访问进行优化,就不会出现错误

                (3)编译器的优化在一般情况下非常好,可以帮助提升程序效率。但是在特殊情况下,变量会被想象之外的力量所改变,此时如果编译器没有意识到而去优化则就会造成优化错误,优化错误就会带来执行错误。而且这种错误很难被发现

                (4)volatile是程序员意识到需要volatile然后在定义变量时加上volatile,如果遇到了应该加上volatile的情况下没有加程序可能会被错误的优化。如果在不应该加volatile而加了的情况下不会出错只是会降低效率。对于volatile的态度应该是:该加的时候加不该加的时候不加,在不确定时候为了保险起见就加上

        6:restrict

                (1)c99才支持,很多延续c89的编译器是不支持的,不过gcc是支持的

                (2)restrict只能修饰指针,不能修饰 普通变量

        7:typdef        

                (1)相关内容在领用一篇博客 http://t.csdnimg.cn/nV3SI中有讲到

                (2)typedef在C语言归类中属于存储类关键字,但是实际上和存储类没有关系

四:作用域详解     

 

        1:局部变量的代码块作用域        

                (1)代码块基本上 可以理解为一对{}括起来的部分。

                (2)代码块不等于函数,if 、while都有{},所以代码块<=函数

                (3)局部变量的作用域是代码块作用域,也就是一个局部变量可以被 访问和使用的范围仅限于定义这个局部变量的代码块的范围内定义这个局部变量之后的部分

        

#include <stdio.h>


void func(void);   //函数声明


int main(void)
{
    
    //如果在main函数内在再定义一个局部变量a
    //int a = 12;            //如果定义了这个的话那么就不会报错,输出的值为12
                              //且局部变量的作用域在这行的开始到'}'这个符号结束
    printf("a = %d\n",a);    //这句话报错

    fanc();

    return 0;

}



void func(void)
{


        int a = 5;
        printf("is a = %d\n",a);


}

报错原因:

局部变量a仅仅只在用户自定义函数func中 能够使用,在这个函数之外的地方程序员无法对这个局部变量a进行任何操作

        2:函数名和全局变量的文件作用域

                (1)文件的作用域的意思就是全局的访问权限,也就是说在整个的.c文件中,都可以访问这些东西

                (2)准确来说,函数和局部变量的作用域是定义所在的整个.c文件之内定义式之后的部分

总结:不管是局部变量、函数、全局变量都要定义声明了之后才能使用,如果在函数后定义了全局变量而没有函数前声明的话,那么是会出现错误的,解决办法就是在函数前声明这个全局变量,这样访问使用这个全局变量就不会出现错误了

#include <stdio.h>

extern int a;   //声明

int main(void)
{


    printf("a = %d\\n",a);


    return 0;

}

int a = 154;            //定义了一个全局变量a

在c89标准的编译器中,所有的局部变量必须定义在最前面,不许在之前有任何一句表达式,在c99的标准中可以运行在代码块内任意地方定义 

        3:同名变量的掩蔽规则

                (1)问题:编程时不可避免会出现同名变量,变量同名不一定会出错

                (2)如果两个同名变量作用域不同且没有交叠,这种情况下同名没有任何影响

                (3)如果两个变量的作用域有交叠,C语言规定在作用域范围内,作用域小的会掩蔽作用域大的

五:变量的生命周期                        

             1:栈变量的生命周期 

                        (1)局部变量(栈变量)存储在栈,生命周期是临时的。临时的意思是说:代码执行过程中按照需要创建、使用、消亡的

                        (2)譬如一个函数内定义的局部变量,在这个函数每次被调用时都会创建一次,然后使用,最后在函数返回时消亡

             2:堆变量的生命周期

                        (1)堆内存空间是客观存在的,是操作系统来维护的。程序员只是去申请使用释放它。

                        (2)程序使用堆内存的这段时间,堆变量也有了生命周期,就是从malloc申请时诞生,然后使用,知道free消亡

                        (3)所以堆内存在malloc之前和free之后不能再去访问,因此堆内存在使用时都是反复的malloc和free的

             3:数据段、bss段变量的生命周期

                

                        (1)全局变量的生命周期是永久的。永久的意思就是在程序执行时诞生,程序终止时消亡

                        (2)全局变量所占用的内存是不能被程序自己释放的,所以如果程序申请了过多的全局变量会导致这个程序一直占用大量内存

             4:代码段、只读段的生命周期

                        (1)其实就是执行的代码,也就是函数,它的生命周期是

       永久的

                        (2)有时候放在代码段的不只是代码,还有const类型的常量。(const类型的常量、字符串有时候放在rodata段,有时候放在代码段,取决于平台)

六:链接属性

                1:C语言程序的组织架构:多个c文件+多个h文件

                        (1)庞大的、一个完整的程序是有多个c文件和h文件组成的

                        (2)程序的生成过程就是编译+链接。编译是为了将函数/变量变成.o二进制的机器码格式,链接是将各个独立分开的

                2:编程以文件为单位、链接以工程文单位

                        (1)编译器工作时是将所有的源文件依次读进来,单个为单位来进行编译的

                        (2)链接的时候实际上是把第一步编译生成的单个.o文件整体的输入,然后处理链接成一个可执行程序

                3:三种链接属性:外链接、内链接、无链接

                         (1)外链接意思就是外部链接属性,也就是说外链接的某个东西可以在整个程序范围内(言下之意就是说可以跨文件)进行链接,譬如普通的函数和全局变量就属于外链接。

                         (2)内链接的意思就是(c文件内部)内部链接属性,也就是这个东西可以在c文件内部范围内进行链接(不能在当前c文件之外的范围内进行访问、链接)。static修饰的全局变量和函数属于内链接

                         (3)无链接的意思就是这个符号本身不进行链接,它和链接没有关系。所有的局部变量(auto、static的)都是无链接的

                4:函数和全局变量的同名冲突

                        (1)因为函数和全局变量是外部链接属性,就是说每一个函数和全局变量将来在整个程序中所有的c文件中都能够被访问,因此在一个程序中的所有c文件不能出现同名函数/同名的全局变量

                        (2)最简单的解决方案就是起名字不要重复,但是很难做到。主要原因是一个很大的工程中函数和全局变量的名字太多了,而且一个大工程不是一个人完成的,是很多人协作进行的,所以很难保证不会重名。

                        (3)现代高级语言的解决这个问题的方法就是命名空间namespace(其实就是给一个变量带上各个级别的前缀)。但是C语言不是这么解决的

                        (4)但是由于C语言出现的太早,比namespase出现的还早,但是C语言就发明了一种不是很完美但是凑合能用的解决方案,就是三种链接属性的方法

                        (5)C语言的链接属性解决重名问题思路是这样的:将不明显不会在其他文件中引用(只在当前c文件中引用)的函数/全局变量,使用static修饰使其成为内链接属性,这样在将来链接时即使有两个重名的函数和全局变量只要其中一个或两个为内部链接属性就没事

                        (6)在一定程度上解决了问题,但是没有在根本上解决问题,留下了很多麻烦。所以这个就导致了C语言写很大型的项目难度很大

                5:static的第二种用法:修饰全局变量和函数

                        (1)普通的(非静态)的函数/全局变量,默认的链接属性是外部的

                        (2)static(静态)的函数/全局变量,链接属性是内部链接

七:总结:

                (1)普通的(自动)局部变量分配在栈上,作用域是在代码块,生命周期是临时的(在{}内当局部变量定义之后),链接属性是无链接。定义时如果未显示初始化则它的值是随机的,变量的地址由运行时在栈上分配得到,多次执行时地址不一定相同,函数不能返回该类变量的地址(指针)作为返回值

                (2)静态局部变量分配在数据段/bss段上(初始化显示为0分配在bss段,非0分配在数据段),作用域是代码块,生命周期为永久,链接属性是无链接。定义时如果未显示初始化则其值为0oy,变量地址由程序运行时环境在加载程序时确定,(地址)整个程序运行过程中唯一不变;静态局部变量其实就是作用域为代码块,链接属性为无链接的的全局变量。静态局部变量可以改用为全局变量实现(尽量不要使用,因为会破坏其结构性)

                (3)全局变量分配在代码段/数据段上(显示初始化为非0分配在数据段,显示初始化为0分配在bss段),作用域是文件作用域,生命周期是永久的,链接属性是外链接。定义时如果未显示初始化则它的值为0,变量地址由程序运行时环境在加载时确定,整个程序运行过程中保持唯一不变;

                (4)静态全局变量分配在数据段/代码段(显示初始化为非0分配在数据段,显示初始化为0分配在bss段),作用域是文件作用域(定义声明之后的整个文件内),生命周期是永久的,链接属性是内链接。定义时如果未显示初始化则它的值为0,变量地址由程序运行时环境在加载时确定的,整个程序运行过程中保持唯一不变

                (5)静态全局变量/静态函数和普通全局变量/普通函数的唯一区别是:static使全局变量/函数的链接属性由外部链接(整个程序所有文件范围)转变为内部链接(当前c文件内部)。这是为了解决全局变量/函数的重名问题(C语言没有命名空间namespace的概念,因此在程序中文件变多之后全局变量/函数重名之后问题会非常的严重,所以程序员可以将不会被其他文件所引用的全局变量/函数声明为static可以很大程度上改善重名的问题,但是还是有问题存在的)

                (6)写重新时尽量避免使用全局变量,尤其是非static类型的全局变量。能确定不会被其他文件引用的全局变量一定要使用static修饰

                (7)注意区分全局变量的定义和声明。一般规律如下:如果定义的同时有初始化则一定会认为是定义:如果只是定义而没有初始化则有可能被编译器认为是定义,也有可能被认为是声明,要具体分析:如果使用extern则肯定会被认为是声明.

                (8)全局变量应该定义在c文件中并且在头文件中声明,而不要定义在头文件中(如果定义在头文件中,则该头文件在被多个c文件包含时该全局变量会出现重复定义)

                (9)要在b.c中引用a.c中定义的全局变量/函数有两种方法:第一中是在a.h中声明该函数/全局变量,然后在b.c中#include(用头文件包含);第二种是在b.c中用extern显示声明要引用的函数/全局变量

                (10)存储类决定生命周期,作用域决定链接属性        

                (11)宏和include的链接为无链接

                             

             

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1807340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Objective-C之通过协议提供匿名对象

概述 通过协议提供匿名对象的设计模式&#xff0c;遵循了面向对象设计的多项重要原则&#xff1a; 接口隔离原则&#xff1a;通过定义细粒度的协议来避免实现庞大的接口。依赖倒置原则&#xff1a;高层模块依赖于抽象协议&#xff0c;而不是具体实现。里氏替换原则&#xff1…

计算机毕业设计 | SpringBoot+vue的教务管理系统

1&#xff0c;绪论 1.1 项目背景 在这个资讯高度发展的时代&#xff0c;资讯管理变革已经是一个更为宽泛、更为全面的潮流。为了保证中国的可持续发展&#xff0c;随着信息化技术的不断进步&#xff0c;教务管理体系也在不断完善。与此同时&#xff0c;伴随着信息化的飞速发展…

Golang-分离式加载器(传参)AES加密

目录 enc.go 生成: dec.go --执行dec.go...--上线 cs生成个c语言的shellcode. enc.go go run .\enc.go shellcode 生成: --key为公钥. --code为AES加密后的数据, ----此脚本每次运行key和code都会变化. package mainimport ("bytes""crypto/aes"&…

好书推荐之《生成式 AI 入门与亚马逊云科技AWS实战》

最近小李哥在亚马逊云科技峰会领到了一本关于如何在云计算平台上设计、开发GenAI应用的书&#xff0c;名字叫&#xff1a;《生成式 AI 入门与亚马逊云科技AWS实战》&#xff0c;今天仔细看了下&#xff0c;发现这本书讲的真的很好&#xff01;他涵盖了当下AI领域所有热门的技术…

《精通ChatGPT:从入门到大师的Prompt指南》第11章:Prompt与AI的未来

第11章&#xff1a;Prompt与AI的未来 11.1 技术发展的新方向 在迅速发展的人工智能领域&#xff0c;Prompt工程作为与AI模型交互的核心方式&#xff0c;正处于技术创新的前沿。未来几年&#xff0c;Prompt工程将沿着多个新方向发展&#xff0c;这些方向不仅会改变我们与AI互动…

Android平台RTMP推送|轻量级RTSP服务|GB28181接入之文字、png图片水印的精进之路

技术背景 Android平台推流模块&#xff0c;添加文字或png水印&#xff0c;不是一件稀奇的事儿&#xff0c;常规的做法也非常多&#xff0c;本文&#xff0c;我们主要是以大牛直播SDK水印迭代&#xff0c;谈谈音视频行业的精进和工匠精神。 第一代&#xff1a;不可动态改变的文…

[ROS 系列学习教程] 建模与仿真 - ros_control 介绍

ROS 系列学习教程(总目录) 本文目录 一、ros_control 架构1.1 hardware_interface1.2 combined_robot_hw1.3 controller_interface1.4 controller_manager1.5 controller_manager_msgs1.6 joint_limits_interface1.7 transmission_interface1.8 realtime_tools 二、ros_control…

LLVM Cpu0 新后端9 objdump readelf

想好好熟悉一下llvm开发一个新后端都要干什么&#xff0c;于是参考了老师的系列文章&#xff1a; LLVM 后端实践笔记 代码在这里&#xff08;还没来得及准备&#xff0c;先用网盘暂存一下&#xff09;&#xff1a; 链接: https://pan.baidu.com/s/1yLAtXs9XwtyEzYSlDCSlqw?…

Android——热点开关(优化中)

SoftAP打开与关闭 目录 1.三个名词的解释以及关系 Tethering——网络共享&#xff0c;WiFi热点、蓝牙、USB SoftAp——热点(无线接入点)&#xff0c;临时接入点 Hostapd——Hostapd是用于Linux系统的软件&#xff0c;&#xff0c;支持多种无线认证和加密协议&#xff0c;将任…

AI大模型在健康睡眠监测中的深度融合与实践案例

文章目录 1. 应用方案2. 技术实现2.1 数据采集与预处理2.2 构建与训练模型2.3 个性化建议生成 3. 优化策略4. 应用示例&#xff1a;多模态数据融合与实时监测4.1 数据采集4.2 实时监测与反馈 5. 深入分析模型选择和优化5.1 LSTM模型的优势和优化策略5.2 CNN模型的优势和优化策略…

LangChain + ChatGLM 实现本地知识库问答

基于LangChain ChatGLM 搭建融合本地知识的问答机器人 1 背景介绍 近半年以来&#xff0c;随着ChatGPT的火爆&#xff0c;使得LLM成为研究和应用的热点&#xff0c;但是市面上大部分LLM都存在一个共同的问题&#xff1a;模型都是基于过去的经验数据进行训练完成&#xff0c;无…

R语言统计分析——数据集概念和数据结构

参考资料&#xff1a;R语言实战.第2版 1、数据集的概念 数据集通常是由数据构成的一个矩形数组&#xff0c;行表示观测&#xff0c;列表示变量。 不同行业对于数据集的行和列叫法不同。统计学称为观测&#xff08;observation&#xff09;和变量&#xff08;variable&#xff…

Nginx高级配置及重写功能

文章目录 一、高级配置网页的状态页Nginx第三方模块变量访问日志Nginx压缩功能https功能自定义小图标 二、重写功能&#xff08;rewrite&#xff09;if指令return指令set指令break指令rewrite指令防盗链 一、高级配置 网页的状态页 状态页显示的是整个服务器的状态而非虚拟主…

LabVIEW在高校中的应用

LabVIEW 作为一款功能强大的图形化编程工具&#xff0c;在高校中有广泛的应用。它不仅用于教学实验&#xff0c;还广泛应用于科研项目和工程训练。本文将从教学、科研、实验室管理和学生技能培养等多个角度&#xff0c;详细分析LabVIEW在高校中的应用。 教学应用 课程设计 自动…

力扣2444.统计定界子数组的数目

力扣2444.统计定界子数组的数目 观察到不满足条件的数 可以作为天然的分割线 因此在枚举右端点的过程中 预处理minK&#xff0c;maxK和分割线上一次出现的下标 res min(min_i,max_i) - i0; 但是因为可能在到下个区段时 min_i和max_i尚未更新 导致结果为负数 所以要跟0再取一…

《Brave New Words 》2.2 阅读理解的未来,让文字生动起来!

Part II: Giving Voice to the Social Sciences 第二部分&#xff1a;为社会科学发声 The Future of Reading Comprehension, Where Literature Comes Alive! 阅读理解的未来&#xff0c;让文字生动起来&#xff01; Saanvi, a ninth grader in India who attends Khan World S…

SOA的设计模式_2.企业服务总线模式

1.企业服务总线&#xff08;|Enterprise Service Bus&#xff0c;ESB&#xff09; 在企业基于SOA实施EAI、B2B和BMP的过程中&#xff0c;如果采用点对点的集成方式存在着复杂度高&#xff0c;可管理性差&#xff0c;复用度差和系统脆弱等问题。企业服务总线&#xff08;…

vuInhub靶场实战系列--Kioptrix Level #2

免责声明 本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关。 目录 免责声明前言一、环境配置1.1 靶场信息1.2 靶场配置 二、信息收集2.1 主机发现2.1.1 netdiscover2.1.2 nmap主机扫描2.1.3 arp-scan主机扫描 2.2 端口扫描…

打字侠是一款PWA网站,如何下载到电脑桌面?

嘿&#xff0c;亲爱的键盘侠们&#xff01; 你是否还在为寻找一款好用的打字练习工具而烦恼&#xff1f;别担心&#xff0c;今天我要给大家介绍一位超级英雄——打字侠&#xff01;它不仅是一个超级酷的打字练习网站&#xff0c;还是一款PWA&#xff08;渐进式网页应用&#x…

Python程序操作MySQL数据库教程

1.Python程序操作MySQL数据库&#xff1a; 使用pymysql安装包 使用&#xff1a; 1.导入pysql包 import pymysql 2.创建连接对象 调用pymysql模块中的connect&#xff08;&#xff09;函数来创建连接对象&#xff0c;代码如下&#xff1a; 连接对象说明&#xff1a; 关闭连接 co…