C语言关键字extern

一.前言

最近写一个代码,编译时老是出现: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 = 1extern int aim放在不同的文件下有4×3=12种情况,那么我们一一试试:

a.ca.hb.cb.h结果
aim=1extern××In function 'dec': 'aim' undeclared
aim=1×extern×输出0 1 0 可用√
aim=1××extern输出0 1 0 可用√
externaim=1××In function 'dec': 'aim' undeclared
×aim=1extern×输出0 1 0 可用√
×aim=1×extern输出0 1 0 可用√
extern×aim=1×输出0 1 0 可用√
×externaim=1×输出0 1 0 可用√
××aim=1extern输出0 1 0 可用√
extern××aim=1b.o:multiple definition of "aim";
a.o:fisrt defiined here
×extern×aim=1b.o:multiple definition of "aim";
a.o:fisrt defiined here
××externaim=1b.o:multiple definition of "aim";
a.o:fisrt defiined here

只定义aim=1

a.ca.hb.cb.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=1b.o:multiple definition of "aim";
a.o:fisrt defiined here

.h声明int aim,在.c实例化int aim = 1

a.ca.hb.cb.h结果
aim=1aim;××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.ca.hb.cb.h结果
aim=1aim;×aim;输出0 1 0可用√
aim=1aim;×extern aim;输出0 1 0可用√
×aim;aim=1aim;输出0 1 0可用√
×extern aim;aim=1aim;输出0 1 0可用√

再来个特殊的:

a.ca.hb.cb.h结果
×int aim;static int aim=1×0 1 -1(这里的aim就是两个变量了哦static的全局作用)
×int aim;×static int aim=1static declaration of 'aim' follows non-static declaration
×static int aim;×static int aim=10 2 -1
static int aim;××static int aim=10 2 -1

四.恶心人的情况

考虑到工程里面经常会出现头文件互相引用的情况,那么将b.c的代码增加一行#include "a.h",现在他们两个互相引用了。那么重复刚才的那些实验:

a.ca.hb.cb.h结果
aim=1extern××输出0 1 0 可用√
aim=1×extern×输出0 1 0 可用√
aim=1××extern输出0 1 0 可用√
externaim=1××b.o:multiple definition of "aim";
a.o:fisrt defiined here
×aim=1extern×b.o:multiple definition of "aim";
a.o:fisrt defiined here
×aim=1×externb.o:multiple definition of "aim";
a.o:fisrt defiined here
extern×aim=1×输出0 1 0 可用√
×externaim=1×输出0 1 0 可用√
××aim=1extern输出0 1 0 可用√
extern××aim=1b.o:multiple definition of "aim";
a.o:fisrt defiined here
×extern×aim=1b.o:multiple definition of "aim";
a.o:fisrt defiined here
××externaim=1b.o:multiple definition of "aim";
a.o:fisrt defiined here

只定义aim=1

a.ca.hb.cb.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=1b.o:multiple definition of "aim";
a.o:fisrt defiined here

.h声明int aim,在.c实例化int aim = 1

a.ca.hb.cb.h结果
aim=1aim;××输出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.ca.hb.cb.h结果
aim=1aim;×aim;输出0 1 0可用√
aim=1aim;×extern aim;输出0 1 0可用√
×aim;aim=1aim;输出0 1 0可用√
×extern aim;aim=1aim;输出0 1 0可用√

五.分析与用法

表格不是所有的情况,但至少可以大致的理解到.c文件和.h文件的作用域。
作为最方便的使用方法:

  • 某个变量需要在其他文件里使用时,直接在其他文件的.hextern声明就好(当然在.c也可以)。
  • .h不要用来实例化,单纯的声明即可。
  • 同一个变量,当它.h声明后,这个变量的作用域就在该.c和.h范围内有效,如果被其他文件的.h嵌套后,这个变量的作用域就从该文件范围拓展到该文件和其他文件。如果在两个文件下有实例化,那么也就等于在同一个作用域有两个实例化,但是这个作用域没有先后顺序的,所以就存在了“同时”给一个变量赋两个值的情况,故会提醒multiple definition

  • 实例化,是指 int aim = 2;。赋值是aim = 2; 两者有很大不同,需要区分开。

六.总结

声明可以拓展作用域,所以可以存在多个,实例化只能有一次。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

康娜喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值