static变量、全局变量及其存储位置、extern关键字

static变量

  1. static变量:在程序执行前系统就为之静态分配(也即在运行时中不再改变分配情况)存储空间的一类变量(无论是否在函数体内都是如此)。

  2. static全局变量:相当于全局变量,但只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它,而extern全局变量可以。

  3. static局部变量:只在定义的函数体内有效,第一次定义时初始化,后续再次进入子函数时不进行初始化,保持上次的值不变。

    void f(){
        static int count=0;
        count++;
        cout<<count<<" ";
    }
    int main() 
    {
        static int count=0;
        for(int i=0;i<3;i++)
            f();
        cout<<count;
        getchar();
    }
    //输出:1 2 3 0
    
  4. 类的static静态成员变量的注意事项:
    通常情况下,类的静态成员变量需要在类外定义及初始化(类似全局变量定义在任何函数之外),因为静态成员变量不是由类的构造函数初始化。

    但是,可以为const整数类型类型的静态成员提供类内初始化,我找到的解释是:因为static const 成员变量会被编译器优化,为编译期常量,编译器不会为其分配内存,如果想取地址还是得在内外定义。

全局变量

全局变量(默认携带extern)、static全局变量和static局部变量的生存期都是“永久”,区别只是可见域不同。extern全局变量可见区域是工程,static全局变量可见区域是文件,而static局部变量的可见区域是块。

静态函数、全局函数的区别同静态全局变量和全局变量的区别,但全局函数不需要extern关键词。

存储位置:
都存储在静态区(全局区),全局变量和静态变量是放在一块的,已初始化的全局变量和静态变量都放在.data段,未初始化以及初始化为0的全局变量和静态变量都放在.bss段。

extern关键字:

extern是一种“外部声明”的关键字,字面意思就是在此处声明某种变量或函数,在外部定义。
或者直接用来定义:

extern int a;//声明一个全局变量a
int a; //定义一个全局变量a

extern int a =0 ;//定义一个全局变量a并给初值。
int a =0;//定义一个全局变量a,并给初值,

第四个 等于 第 三个,都是定义一个可以被外部使用的全局变量,并给初值。
但是定义只能出现在一处,也就是说,不管是int a,还是extern int a=0;还是int a=0;都只能出现一次,而extern int a可以出现很多次。

注意:const修饰的变量是内部连接,extern无法引用其他文件的const常量。

extern “C” :

由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。
因此,如果想在C++代码中使用.c文件中实现的函数,需要在头文件中 使用extern "C"来修饰 对应的函数声明。

//moduleA.h
#ifndef __MODULE_A_H 
#define __MODULE_A_H
int fun(int, int);
#endif
 
//moduleA.C 
//模块A的实现部分并没有改变
#include"moduleA"
int fun(int a, int b)
{
	return a+b;
}
 
//moduleB.h
#idndef __MODULE_B_H 
#define __MODULE_B_H
#ifdef __cplusplus //为cpp文件默认定义了该宏,以此判断是否是cpp文件
extern "C"{ 
#endif

#include"moduleA.h"//其他代码
 
#ifdef __cplusplus
}
#endif

#endif
 
//moduleB.cpp 
//B模块的实现也没有改变,只是头文件的设计变化了
#include"moduleB.h"
int main()
{
  cout<<fun(2,3)<<endl;
}

初始化时间

静态局部变量和全局变量一样,数据都存放在全局区域,所以在主程序之前,编译器已经为其分配好了内存。但在C和C++中静态局部变量的初始化节点不一样

在C中,初始化发生在代码执行之前,编译阶段分配好内存之后,就会进行初始化,所以我们看到在C语言中无法使用变量对静态局部变量进行初始化。

而在C++中,引入了对象、构造函数,初始化时需要执行相关代码,无法在编译期完成。因此规定,全局变量、静态变量和类的静态成员变量在main执行之前初始化;局部静态变量在第一次使用时初始化。并且,可以使用变量对全局变量初始化,因此,可以借此在进入main函数前执行代码

#include <bits/stdc++.h>
using namespace std;
struct A{
    A() { cout<<"A构造"<<endl;};
    void f(){}
};

struct B{
    B() { cout<<"B构造"<<endl;};
};

void fun(){
    static B b;
}

A genA(){
    cout<<"!!!!!!!"<<endl;
    A a;
    return a;
}

static A a = genA();

int main()
{
    cout<<"——————"<<endl;
    fun();
    a.f();
}

输出:

!!!!!!!
A构造
——————
B构造
  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值