当前位置:网站首页>C语言关键字extern
C语言关键字extern
2022-07-26 07:25:00 【康娜喵】
一.前言
最近写一个代码,编译时老是出现:multiple definition,想到太恼火了,那就枚举一下可能出现的情况,再总结一下。
二.代码
编译环境:gcc version 9.4.0 (Ubuntu 9.4.0-1Ubuntu1~20.04)
- a.c
#include <stdio.h>
#include "a.h"
#include "b.h"
int add()
{
printf("%d\n", ++aim);
}
int main()
{
dec();
add();
dec();
return 0;
}
- a.h
#ifndef _A_H
#define _A_H
int add();
#endif
- b.c
#include <stdio.h>
#include "b.h"
int dec()
{
printf("%d\n", --aim);
}
- b.h
#ifndef _B_H
#define _B_H
int dec();
#endif
- makefile
TARGET:=./out
obj-y:=a.c b.c
OBJS=$(patsubst %.c, %.o, $(obj-y))
all:clean $(TARGET)
@./out
$(TARGET):$(OBJS)
@gcc -o $(TARGET) $(OBJS)
%.o:%.c
@gcc $(CFLAGS) -c $<
clean:
@rm -rf $(OBJS) $(TARGET)
三.排列组合
把int aim = 1 和 extern int aim放在不同的文件下有4×3=12种情况,那么我们一一试试:
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| aim=1 | extern | × | × | In function 'dec': 'aim' undeclared |
| aim=1 | × | extern | × | 输出0 1 0 可用√ |
| aim=1 | × | × | extern | 输出0 1 0 可用√ |
| extern | aim=1 | × | × | In function 'dec': 'aim' undeclared |
| × | aim=1 | extern | × | 输出0 1 0 可用√ |
| × | aim=1 | × | extern | 输出0 1 0 可用√ |
| extern | × | aim=1 | × | 输出0 1 0 可用√ |
| × | extern | aim=1 | × | 输出0 1 0 可用√ |
| × | × | aim=1 | extern | 输出0 1 0 可用√ |
| extern | × | × | aim=1 | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| × | extern | × | aim=1 | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| × | × | extern | aim=1 | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
只定义aim=1
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| aim=1 | × | × | × | In function 'dec': 'aim' undeclared |
| × | aim=1 | × | × | In function 'dec': 'aim' undeclared |
| × | × | aim=1 | × | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| × | × | × | aim=1 | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
在.h声明int aim,在.c实例化int aim = 1
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| aim=1 | aim; | × | × | In function 'dec': 'aim' undeclared |
| aim=1 | × | aim=1 | × | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| aim=1 | × | × | aim; | 输出0 1 0 可用√ |
| × | aim; | aim=1 | × | 输出0 1 0可用√ |
| × | aim; | × | aim; | 输出-1 0 -1 也可用 |
理想的标准化写法:
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| aim=1 | aim; | × | aim; | 输出0 1 0可用√ |
| aim=1 | aim; | × | extern aim; | 输出0 1 0可用√ |
| × | aim; | aim=1 | aim; | 输出0 1 0可用√ |
| × | extern aim; | aim=1 | aim; | 输出0 1 0可用√ |
再来个特殊的:
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| × | int aim; | static int aim=1 | × | 0 1 -1(这里的aim就是两个变量了哦static的全局作用) |
| × | int aim; | × | static int aim=1 | static declaration of 'aim' follows non-static declaration |
| × | static int aim; | × | static int aim=1 | 0 2 -1 |
| static int aim; | × | × | static int aim=1 | 0 2 -1 |
四.恶心人的情况
考虑到工程里面经常会出现头文件互相引用的情况,那么将b.c的代码增加一行#include "a.h",现在他们两个互相引用了。那么重复刚才的那些实验:
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| aim=1 | extern | × | × | 输出0 1 0 可用√ |
| aim=1 | × | extern | × | 输出0 1 0 可用√ |
| aim=1 | × | × | extern | 输出0 1 0 可用√ |
| extern | aim=1 | × | × | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| × | aim=1 | extern | × | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| × | aim=1 | × | extern | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| extern | × | aim=1 | × | 输出0 1 0 可用√ |
| × | extern | aim=1 | × | 输出0 1 0 可用√ |
| × | × | aim=1 | extern | 输出0 1 0 可用√ |
| extern | × | × | aim=1 | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| × | extern | × | aim=1 | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| × | × | extern | aim=1 | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
只定义aim=1
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| aim=1 | × | × | × | In function 'dec': 'aim' undeclared |
| × | aim=1 | × | × | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| × | × | aim=1 | × | In function 'add': 'aim' undeclared |
| × | × | × | aim=1 | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
在.h声明int aim,在.c实例化int aim = 1
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| aim=1 | aim; | × | × | 输出0 1 0 可用√ |
| aim=1 | × | aim=1 | × | b.o:multiple definition of "aim"; a.o:fisrt defiined here |
| aim=1 | × | × | aim; | 输出0 1 0 可用√ |
| × | aim; | aim=1 | × | 输出0 1 0可用√ |
| × | aim; | × | aim; | 输出-1 0 -1 也可用 |
理想的标准化写法:
| a.c | a.h | b.c | b.h | 结果 |
|---|---|---|---|---|
| aim=1 | aim; | × | aim; | 输出0 1 0可用√ |
| aim=1 | aim; | × | extern aim; | 输出0 1 0可用√ |
| × | aim; | aim=1 | aim; | 输出0 1 0可用√ |
| × | extern aim; | aim=1 | aim; | 输出0 1 0可用√ |
五.分析与用法
表格不是所有的情况,但至少可以大致的理解到.c文件和.h文件的作用域。
作为最方便的使用方法:
- 某个变量需要在其他文件里使用时,直接在其他文件的
.h用extern声明就好(当然在.c也可以)。 .h不要用来实例化,单纯的声明即可。- 同一个变量,当它
.h声明后,这个变量的作用域就在该.c和.h范围内有效,如果被其他文件的.h嵌套后,这个变量的作用域就从该文件范围拓展到该文件和其他文件。如果在两个文件下有实例化,那么也就等于在同一个作用域有两个实例化,但是这个作用域没有先后顺序的,所以就存在了“同时”给一个变量赋两个值的情况,故会提醒multiple definition
注:
- 实例化,是指
int aim = 2;。赋值是aim = 2;两者有很大不同,需要区分开。
六.总结
声明可以拓展作用域,所以可以存在多个,实例化只能有一次。
边栏推荐
- Performance test -- lockust performs seckill business scenario test
- Taishan Office Technology Lecture: page width, height, size and source, and the conversion relationship between inches, centimeters and DPI
- MySQL安装教程-手把手教你安装
- Embedded development: tools -- intelligent watchdog design
- TensorFlow学习日记之tflearn
- hot100 哈希
- How to convert multi row data into multi column data in MySQL
- NFT digital collection system development: Huawei releases the first collector's digital collection
- China Unicom transformed the Apache dolphin scheduler resource center to realize the one-stop access of cross cluster call and data script of billing environment
- With someone else's engine, can it be imitated?
猜你喜欢

PXE高效批量网络装机

NFT数字藏品系统开发:激活数字文化遗产

Become an Apache contributor, so easy!

redis-migrate-tool迁移报错。

Hcip - MPLS Technology

Leetcode 1184: distance between bus stops

NFT digital collection development: Six differences between digital collections and NFT

WCF 入门教程二
![Rgb-t tracking - [dataset benchmark] gtot / rgbt210 / rgbt234 / vot-2019-2020 / laser / VTUAV](/img/10/40d02da10a6f6779635dc820c074c6.png)
Rgb-t tracking - [dataset benchmark] gtot / rgbt210 / rgbt234 / vot-2019-2020 / laser / VTUAV

No .egg-info directory found in xxx\pip-pip-egg-info-mq
随机推荐
China Unicom transformed the Apache dolphin scheduler resource center to realize the one-stop access of cross cluster call and data script of billing environment
NFT数字藏品系统开发:华为发布首款珍藏版数字藏品
Download and install the free version of typora
MySQL installation tutorial - hands on installation
Apache Dolphinscheduler3.0.0-beta-1 版本发布,新增FlinkSQL、Zeppelin任务类型
3.0.0 alpha 重磅发布!九大新功能、全新 UI 解锁调度系统新能力
WCF 入门教程二
anaconda安装教程-手把手教你安装
Embedded development: tools -- intelligent watchdog design
此章节用于补充2
倒计时2日!基于 Apache DolphinScheduler&TiDB 的交叉开发实践,从编写到调度让你大幅提升效率
依赖和关联的对比和区别
Anaconda installation tutorial - hands on installation
C51与MDK共存 Keil5安装教程
Task 1 Titanic top 4% with ensemble modeling
Taishan Office Technology Lecture: how to calculate page blank (margin)
数据平台调度升级改造 | 从Azkaban 平滑过度到 Apache DolphinScheduler 的操作实践
此章节用于补充
HCIP --- MPLS技术
Leetcode:1898. maximum number of removable characters [if you want to delete some IDX from a pile of things, don't use pop]