迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > C语言 >

详细了解 static 和 extern 关键字的用法

作者:迹忆客 最近更新:2023/05/09 浏览次数:

C语言 static 和 extern关键字


static

一、 static函数 和 普通函数 区别

总的来说,static函数和普通函数的区别就是体现在作用域上面。static函数只是在本文件起作用。不可以被其他文件调用。先举个例子

例一

math.c

static int add(int a,int b)
{
    return a+b;
}

main.c

#include <stdio.h>

int main() {
    int a = 10,b=22;
    printf("%d!\n",add(a,b));
    return 0;
}

对上面文件用gcc进行编译

$ gcc main.c math.c

结果如下

main.c:15:20: warning: implicit declaration of function 'add' is invalid in C99
      [-Wimplicit-function-declaration]
    printf("%d!\n",add(a,b));
                   ^
1 warning generated.
Undefined symbols for architecture x86_64:
  "_add", referenced from:
      _main in main-eaa78d.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

很明显的错误就是main.c文件中的函数 add 未定义。

我们做一下修改,加一个.h头文件

math.h

static int add(int a,int b);

main.c中引入

#include <stdio.h>
#include "math.h"

int main() {
    int a = 10,b=22;
    printf("%d!\n",add(a,b));
    return 0;
}

再次使用gcc进行编译

$ gcc main.c math.c

结果是一样的

./math.h:8:12: warning: function 'add' has internal linkage but is not defined
      [-Wundefined-internal]
static int add(int a,int b);
           ^
main.c:15:20: note: used here
    printf("%d!\n",add(a,b));
                   ^
1 warning generated.
Undefined symbols for architecture x86_64:
  "_add", referenced from:
      _main in main-c5f44a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

这说的是add函数已经声明了,但是在main.c中并没有定义(虽然在 math.c中有定义,但是函数是static类型的,只在math.c文件中可见)。
有两种方式修改
一)将math.c中的函数改成普通函数

int add(int a,int b)
{
    return a+b+10;
}

gcc编译会产生警告

main.c:15:20: warning: implicit declaration of function 'add' is invalid in C99
      [-Wimplicit-function-declaration]
    printf("%d!\n",add(a,b));
                   ^
1 warning generated.

但是程序是可以正常执行的。要去除警告可以在math.h中声明普通函数,然后在main.c中引入math.h

int add(int a,int b);

二)在main.c中定义add()函数

#include <stdio.h>

static int add(int a,int b)
{
    return a+b;
}

int main() {
    int a = 10,b=22;
    printf("%d!\n",add(a,b));
    return 0;
}

千万注意的是,不可以同时在两个文件中定义普通的add函数。例如

例二

math.c

int add(int a,int b)
{
    return a+b+10;
}

main.c

#include <stdio.h>

int add(int a,int b)
{
    return a+b;
}
int main() {
    int a = 10,b=22;
    printf("%d!\n",add(a,b));
    return 0;
}

这样是会报错的,函数被重复定义。所以说,从另一方面,static允许在不同文件中定义同名函数,这也是static函数除作用域之外的另一用途。

二、static变量 和 普通变量区别

static变量和static函数异曲同工,也是对作用域的限定。


extern

一、变量前加extern关键字

对于函数有声明定义两步。同样对于变量严格来说也是分声明定义。定义一个变量就要为其分配内存并赋值。如果没指定值则根据变量类型赋相应的默认值。

int var1;  // 相当于是  声明和定义合成为一步
extern int var2; // 仅仅是声明

也就是说在变量前面如果加上了extern关键字,对于这个变量来说只是进行了声明并没有定义。下面举几个例子进行对extern的用法进行说明

例一

main.c

#include <stdio.h>

int var1;
extern int var2;

int main()
{
    var1 = 11;
    var2 = 12;
    printf("var1=%d; var2=%d\n",var1,var2);
    return 0;
}

gcc进行编译

$ gcc main.c

Undefined symbols for architecture x86_64:
  "_var2", referenced from:
      _main in main-179d3c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

链接的时候没有找到变量var2。因为var2只是进行了声明,并没有定义,所以编译能通过,到了链接的时候就找不到了。

例二

main.c

#include <stdio.h>

int var1 = 11;
extern int var2 = 12;
int main() {
    printf("var1=%d; var2=%d\n",var1,var2);
    return 0;
}

gcc进行编译

$ gcc main.c

main.c:5:12: warning: 'extern' variable has an initializer [-Wextern-initializer]
extern int var2 = 12;
           ^
1 warning generated.

只是一个警告,程序是可以正确执行的。也就是说 extern int var2 = 12 这种方式也是对变量进行了定义,但这是不合规则的,所以给你个警告。

extern 主要是对外部变量进行引用。所以正确合规的用法举例如下

例三

math.c

int var = 12;

main.c

#include <stdio.h>

extern int var;

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

gcc进行编译

$ gcc main.c math.c

没有问题。 因为 var 变量是进行了定义的。 所以在main.c中是可以找到var变量的。

例四

math.c

extern int var = 12;

main.c

#include <stdio.h>

extern int var;

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

gcc 进行编译

$ gcc main.c math.c
static/math.c:61:12: warning: 'extern' variable has an initializer [-Wextern-initializer]
extern int var = 12;
           ^
1 warning generated.

也是可以通过的,只是多了一个警告。参照 例二

总的来说,只要是一个全局变量进行了定义。在其他文件中通过extern关键字就可以进行引用。

二、extern 函数

函数默认都是extern类型的。也就是说函数前面没有static关键字修饰,那就都是extern

int add(int a, int b);
// 等价于
extern int add(int a, int b);

上面关于 extern 修饰的变量,必须要是定义的全局变量,在其他文件中才能通过 extern 进行引用。 函数内定义的变量是没法被其他文件进行引用的。

上一篇:没有了

下一篇:C 线程资源释放问题

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Do you understand JavaScript closures?

发布时间:2025/02/21 浏览次数:108 分类:JavaScript

The function of a closure can be inferred from its name, suggesting that it is related to the concept of scope. A closure itself is a core concept in JavaScript, and being a core concept, it is naturally also a difficult one.

Do you know about the hidden traps in variables in JavaScript?

发布时间:2025/02/21 浏览次数:178 分类:JavaScript

Whether you're just starting to learn JavaScript or have been using it for a long time, I believe you'll encounter some traps related to JavaScript variable scope. The goal is to identify these traps before you fall into them, in order to av

How much do you know about the Prototype Chain?

发布时间:2025/02/21 浏览次数:150 分类:JavaScript

The prototype chain can be considered one of the core features of JavaScript, and certainly one of its more challenging aspects. If you've learned other object-oriented programming languages, you may find it somewhat confusing when you start

Vue - An In-Depth Guide to Lifecycle Hooks

发布时间:2025/02/21 浏览次数:117 分类:Vue

Vue has many lifecycle hooks, and it can be confusing to understand the meaning or purpose of each one. In this article, we will explain the function of each lifecycle hook and how to use them.

Solution for Flickering During Vue Template Parsing

发布时间:2025/02/21 浏览次数:103 分类:Vue

Solution for Flickering During Vue Template Parsing, Recently, while working on a project, I noticed that when the internet speed is slow, the screen flickers and the expression message appears. This happens because when the internet speed i

Pandas read_csv()函数

发布时间:2024/04/24 浏览次数:254 分类:Python

Pandas read_csv()函数将指定的逗号分隔值(csv)文件读取到 DataFrame 中。

Pandas 追加数据到 CSV 中

发布时间:2024/04/24 浏览次数:352 分类:Python

本教程演示了如何在追加模式下使用 to_csv()向现有的 CSV 文件添加数据。

Pandas loc vs iloc

发布时间:2024/04/24 浏览次数:837 分类:Python

本教程介绍了如何使用 Python 中的 loc 和 iloc 从 Pandas DataFrame 中过滤数据。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便