C语言 static extern 关键字详解

C语言 static 关键字详解

  • [1 全局变量](#1 全局变量)
  • [2 static 修饰全局变量](#2 static 修饰全局变量)
  • [3 static 修饰局部变量](#3 static 修饰局部变量)
  • [4 static 修饰函数](#4 static 修饰函数)
  • [5 extern 关键字](#5 extern 关键字)

在C语言中主要是用来修饰变量和函数

1 全局变量

全局变量的作用域十分的广,只要在一个源文件中定义后,应用中所有的所有源文件、对象以及函数都可以调用,生命周期更是贯穿整个程序

代码说明

文件 global_test.cpp

cpp 复制代码
int g_num = 100;//定义全局变量

文件 main.cpp

cpp 复制代码
extern int g_num;//声明全局变量 不需要包含头文件 也可以引用 使用extern关键字

int32 get_g_num();

int main()
{
    get_g_num();
    return 0;
}

int32 get_g_num()
{
    return g_num;
}

2 static 修饰全局变量

  1. static 修饰全局变量其作用域会被限制在当前文件中

文件 global_test.cpp

cpp 复制代码
#include "global_test.h"
// 如果全局变量被static修饰
// 那这个外部链接属性就会被修改成内部链接属性,
// 此时这个全局变量就只能在自己的源文件中使用;
static int g_num = 100;//static 修饰全局变量 变量的作用域会被限制在当前文件中

文件 main.cpp

cpp 复制代码
#include "keyword.h"
extern int g_num;//声明全局变量 不需要包含头文件 也可以引用 使用extern关键字
int main()
{
    printf("g_num = %d\n",g_num);
    return 0;
}

此时编译会发现没有定义变量 g_num 说明 g_num被限制在了 global_test.cpp

其本质是

全局变量本身是具有外部链接属性的,在A文件中定义的全局变量,在B文件中可以通过【链接】来使用;

但如果全局变量被static修饰,那这个外部链接属性就会被修改成内部链接属性,此时这个全局变量就只能在自己的源文件中使用

  1. 对static全局变量的修改对其他文件不可见

在另一个头文件中包含定义有静态全局变量头文件,此静态全局变量可以被引用

文件 global_test.h

cpp 复制代码
static int g_num = 100;

文件 test.h

cpp 复制代码
#ifndef KEYWORD_H
#define KEYWORD_H
#include "ctest.h"
#include "global_test.h" 
int32 print_g_num();
#endif // KEYWORD_H

文件 test.cpp

cpp 复制代码
#include "keyword.h"

int32 print_g_num()
{
    // 在 global_test.h 头文件中定义的静态全局变量在文件被包含之后可以被正常访问
    printf("g_num = %d",g_num);
    return 0;
}

文件 main.c

cpp 复制代码
#include <stdio.h>
#include "test.h"
int main()
{
    print_g_num();
    return 0;
}

静态全局变量被多次包含会出现重复定义错误么? 答案是不会 接下来验证

test_2.cpp中包含头文件 global_test.h

cpp 复制代码
#include "global_test.h"
#include "stdio.h"
int print_g_num_1()
{
    printf("g_num = %d\n",g_num);
    return 0;
}

文件 main.c

cpp 复制代码
#include <stdio.h>
#include "test.h"
extern int print_g_num_1();//函数声明
int main()
{
    print_g_num();// 正常访问 g_num
    print_g_num_1();// 正常访问 g_num
    return 0;
}

如果将 global_test.h 中的 static 关键字去掉,则上述代码编译之后会出现重复定义错误

在一个文件中对静态全局变量进行修改对其他文件不可见

global.h

cpp 复制代码
#ifndef GLOBAL_TEST_H
#define GLOBAL_TEST_H
static int g_num = 100;//定义静态全局变量
int set_num_3(int num);
int print_num_3();
#endif // GLOBAL_TEST_H

global.c

cpp 复制代码
#include "global_test.h"
int set_num_3(int num)
{
    printf("set_num_1 modi befor g_num = %d\n",g_num);
    g_num  = num;
}

int print_num_3()
{
    printf("g_num = %d\n",g_num);
    return 0;
}

test.c

cpp 复制代码
int print_num_1()
{
    printf("g_num = %d\n",g_num);
    return 0;
}

int set_num_1(int num)
{
    printf("set_num_1 modi befor g_num = %d\n",g_num);
    g_num  = num;
}
cpp 复制代码
#include "global_test.h"
#include "stdio.h"
int print_g_num_1()
{
    printf("g_num = %d\n",g_num);
    return 0;
}

int set_num_2(int num)
{
    printf("set_num_1 modi befor g_num = %d\n",g_num);
    g_num  = num;
}

int print_num_2()
{
    printf("g_num = %d\n",g_num);
    return 0;
}

main.c

cpp 复制代码
#include <stdio.h>
#include "test.h"
#include "global_test.h"
//函数声明
extern int print_g_num_1();
extern int set_num_1(int);
extern int set_num_2(int);
extern int print_num_1();
extern int print_num_2();

int main()
{
     set_num_3(3);
     print_num_3();

     set_num_2(2);
     print_num_2();

     set_num_1(1);
     print_num_1();
}

输出结果

从输出结果可以得出结论 :

对静态全局变量的修改对其他文件是不可见的,相当于每个文件中都有一份初始的值,都一样,各自修改各自的,互不影响


3 static 修饰局部变量

coding
test.c

cpp 复制代码
int  local_var_test()
{
    /**
       * 局部变量只是在第一次调用时会被初始化一次 数据是存储在全局区
       */
    static int index = 0;
    index ++;
    printf("index =  %d \n",index);
    return 0;
}

int  test()
{
    for (int i = 0;i < 10;++i){
         local_var_test();
    }
}

main.c

cpp 复制代码
extern int  test();
int main()
{
    test();
}

output

index = 1

index = 2

index = 3

index = 4

index = 5

index = 6

index = 7

index = 8

index = 9

index = 10


4 static 修饰函数

在上面的代码中 我们只需要在 main.c中 声明 函数,即可完成对函数的调用

现在我们把函数声明为静态函数,即使用 static修饰,则此函数将会被限制在所在文件中,使用extern关键字也无法调用该函数

test.c

cpp 复制代码
static int static_func_test()
{
    printf("static_func_test \n");
    return 0;
}
cpp 复制代码
extern static_func_test();
int main()
{
    static_func_test();
}

此时编译报错,没有定义引用 static_func_test

函数本身也是有外部链接属性的;

被static修饰后,函数的外部链接属性被修改成内部链接属性,使得这个函数只能在自己的源文件内被使用,因此函数的作用域就变小了。


5 extern 关键字

extern 是一种外部声明的关键字,字面意思就是在此处声明某种变量或函数,在外部定义。

1 修饰变量

在其它文件中定义变量

c 复制代码
int extern_val = 100;//定义变量 并进行初始化

在当前文件中引用变量

c 复制代码
#include <stdio.h>
extern int extern_val;//声明变量 表示此处要进行引用
int main()
{
    printf("extern_val = %d\n",extern_val);
    return 0;
}

2 修饰函数

在其它头文件中定义函数

c 复制代码
// 函数的定义
int printArr(int* pIntArr,int ilen){
    if (pIntArr == NULL || ilen == 0)
    {
        return 0;
    }
    for (int index = 0; index < ilen; index++){
        printf("%d ",pIntArr[index]);
    }
    return 0;
}

声明并引用函数

c 复制代码
extern int printArr(int* pIntArr,int ilen);//函数的声明
int main()
{
    int intArr[] = {1,20,7,3,12};
    printArr(intArr,sizeof(intArr) / sizeof(int));
    return 0;
}
相关推荐
这是我5827 分钟前
C++掉血迷宫
c++·游戏·visual studio·陷阱·迷宫·生命·
学习使我变快乐31 分钟前
C++:初始化列表
开发语言·c++·算法
小周的C语言学习笔记31 分钟前
鹏哥C语言40---函数参数与函数调用
c语言·数据结构·算法
CV金科33 分钟前
蓝桥杯-STM32G431RBT6(串口)
c语言·stm32·单片机·嵌入式硬件·蓝桥杯
DXCcn35 分钟前
[语言月赛 202408] 两座城市的 543 千米
c++
破刺不会编程37 分钟前
【C++】透析string类
c语言·开发语言·数据结构·c++
wxin_VXbishe1 小时前
springboot瑜伽课约课小程序-计算机毕业设计源码87936
java·c++·spring boot·python·spring·servlet·php
Jcqsunny1 小时前
[atcoder agc 004 c] AND Grid
c++·算法·构造
suiyi_freely1 小时前
c++二叉搜索树
开发语言·c++
毅凉2 小时前
Linux笔记
linux·c语言·网络·数据库