• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

Recommended Posts

我们知道,变量是有数据类型的,数据类型是用来说明它们占用了多少内存空间,可以执行什么样的操作。

除了数据类型,变量还有一个属性叫做“存储类别”。类别是变量在内存中的存储区域。在进程的地址空间中,常量区、全局数据区和堆栈区可以用来存储变量的值。

常量区和全局数据区的内存在程序启动时就已经被操作系统分配了,占用的空间是固定的,在程序运行过程中不会改变,只有在程序运行后才会被操作系统释放;它可以存储全局变量、静态变量、通用常量和字符串常量。

堆栈的内存由系统在程序运行过程中根据需要分配(只有在使用变量时才分配内存;如果定义了变量但代码没有执行,内存就不会分配),占用的空间会实时变化,用完后马上释放,不用等到程序运行结束;它可以存储局部变量、函数参数等。

在C语言中我们可以通过关键字来控制变量的存储区域。C中有四个关键字来表示变量的存储类别:auto(自动)、static(静态)、register(注册)和extern(外部)。

知道了变量的存储类别,就可以知道变量的生存期。一般来说,生存期是指程序运行过程中变量从创建到销毁的时间。生存期的长短取决于变量的存储类别,也就是它所在的内存区域。

在本节中,我们只解释三个关键词:auto、static和register。外部将在模块化开发中解释它们。

auto 变量

Auto表示自动或默认,很少使用,因为默认情况下所有变量都是auto。也就是说,定义变量的时候加不加auto都一样,所以一般会省略,不用做很多次。

例如:

int n=10

auto int n=10

效果完全一样。

static 变量

由static声明的变量称为静态变量,无论是全局变量还是局部变量,都存储在静态数据区(全局变量已经存储在静态数据区,即使没有static)。

当程序启动时,静态数据区中的数据将被初始化,直到程序结束。对于代码块中的静态局部变量,即使代码块完成了,也不会被销毁。

注意:静态数据区的一个变量只能初始化(定义)一次,它的值只能在后面更改,不能再次初始化。即使这样的声明也是无效的。

请看下面的代码:

#包含stdio.h

#包含stdlib.h

int main()

{

int结果,I;

for(I=1;i=100i ){

结果=总和(I);

}

printf('1 2 3.99 100=%d\n ',结果);

系统(“暂停”);

返回0;

}

int sum(int n){

//可以不赋初始值0,静态数据区的变量默认初始化为0。

静态int结果=0;

结果=n;

返回结果;

}

运行结果:

1 2 3 .99 100=5050

我们在sum()中定义了一个静态局部变量result,它存储在静态数据区中。sum()函数在执行结束时不会被销毁,在下一次调用时仍然有效。静态数据区中的变量只能初始化一次。第一次调用sum()时结果已经初始化,所以再次调用时不会初始化,也就是说static int result=0;无效语句。

尽管局部变量存储在静态数据区,但它的范围仅限于定义它的代码块。sum()中的结果在函数外是无效的,与main()中的结果不冲突,除了变量名之外与它无关。

register 变量

通常,变量的值存储在内存中,CPU每次使用它们时都会从内存中读取数据。如果一些变量使用非常频繁,从内存中读取会花费很多时间,比如for循环中的增量控制:

int I;

for(I=0;i1000i ){

//一些代码

}

执行这段代码,CPU将读取内存1000次,以获得I。

为了解决这个问题,可以将经常使用的变量放在CPU的通用寄存器中,这样在使用这个变量时,就不需要访问内存,直接从寄存器中读取,大大提高了程序的运行效率。

但是寄存器的数量是有限的,最常用的变量通常被定义为寄存器。

我们来看一个计算的近似值的例子。待求解的近似公式如下:

ps://www.icode9.com/i/l/?n=22&i=blog/1852906/202205/1852906-20220502173855341-282021075.png"/>

 为了提高精度,循环的次数越多越好,可以将循环的增量控制定义为寄存器变量,如下所示:

#include <stdio.h>
#include <conio.h>
int main()
{
    register int i = 0;  // 寄存器变量
    double sign = 1.0, res = 0, ad = 1.0;
    for(i=1; i<=100000000; i++)
    {
        res += ad;
        sign=-sign;
        ad=sign/(2*i+1);
    }
    res *= 4;
    printf("pi is %f", res);
    getch();
    return 0;
}

运行结果:

pi is 3.141593

关于寄存器变量有以下事项需要注意:

1) 为寄存器变量分配寄存器是动态完成的,因此,只有局部变量和形式参数才能定义为寄存器变量。

2) 局部静态变量不能定义为寄存器变量,因为一个变量只能声明为一种存储类别。

3) 寄存器的长度一般和机器的字长一致,只有较短的类型如 int、char、short 等才适合定义为寄存器变量,诸如 double 等较大的类型,不推荐将其定义为寄存器类型。

4) CPU的寄存器数目有限,即使定义了寄存器变量,编译器可能并不真正为其分配寄存器,而是将其当做普通的auto变量来对待,为其分配栈内存。当然,有些优秀的编译器,能自动识别使用频繁的变量,如循环控制变量等,在有可用的寄存器时,即使没有使用 register 关键字,也自动为其分配寄存器,无须由程序员来指定。   

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now