在C和C ++中不使用extern的不同编译结果 [英] Different compilation results not using extern in C vs in C++

查看:113
本文介绍了在C和C ++中不使用extern的不同编译结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在两个不同的源文件中声明一个全局变量并仅在其中一个源文件中定义它时,C ++的编译结果与C的编译结果不同.请参见以下示例:

When I declare a global variable in two different source files and only define it in one of the source files, I get different results compiling for C++ than for C. See the following example:

#include <stdio.h>
#include "func.h" // only contains declaration of void print();

int def_var = 10;

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

func.c

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

/* extern */int def_var; // extern needed for C++ but not for C?

void print() {
    printf("%d\n", def_var);
}

我使用以下命令进行编译:

I compile with the following commands:

gcc/g++ -c main.c -o main.o
gcc/g++ -c func.c -o func.o
gcc/g++ main.o func.o -o main

g ++/clang ++抱怨multiple definition of def_var(这是我不使用extern时所期望的行为). gcc/clang编译就好了. (使用gcc 7.3.1和clang 5.0)

g++/clang++ complain about multiple definition of def_var (this is the behaviour I expected, when not using extern). gcc/clang compile just fine. (using gcc 7.3.1 and clang 5.0)

根据此链接:

暂定定义是可以或可以不充当定义的声明.如果在同一翻译单元中早晚发现了实际的外部定义,则该暂定定义仅充当声明.

A tentative definition is a declaration that may or may not act as a definition. If an actual external definition is found earlier or later in the same translation unit, then the tentative definition just acts as a declaration.

因此,我的变量def_var应该在每个翻译单元的末尾定义,然后产生多个定义(对于C ++来说是这样).为什么用gcc/clang编译时不是这种情况?

So my variable def_var should be defined at the end of each translation unit and then result in multiple definitions (as it is done for C++). Why is that not the case when compiling with gcc/clang?

推荐答案

严格来讲,这也不是有效的C语言.用

This isn't valid C either, strictly speaking. Says as much in

6.9外部定义-p5

外部定义是一个外部声明,它也是一个 函数的定义(内联定义除外)或 目的.如果在外部链接中使用通过外部链接声明的标识符 表达式(不是作为sizeof或_Alignof的操作数的一部分 运算符,其结果是一个整数常量),在整个位置上 程序中应该只有一个外部定义 标识符否则,最多只能有一个.

An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.

对于具有外部链接的标识符,您有两个定义.您违反了该要求,行为是不确定的.链接和工作的程序并不反对这一点.不需要诊断.

You have two definitions for an identifier with external linkage. You violate that requirement, the behavior is undefined. The program linking and working is not in opposition to that. It's not required to be diagnosed.

值得注意的是,C ++在这方面没有什么不同.

And it's worth noting that C++ is no different in that regard.

[basic.def.odr]/4

每个程序应仅包含每个非内联的一个定义 该程序之外的函数或变量 废弃的陈述;无需诊断.定义可以出现 可以在标准程序中找到 用户定义的库,或(如果适用)隐式定义 (请参阅[class.ctor],[class.dtor]和[class.copy]).内联函数 或变量应在其所在的每个翻译单元中定义 在废弃的语句之外使用.

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see [class.ctor], [class.dtor] and [class.copy]). An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement.

同样,这是一个必须"的要求,它明确表示不需要诊断.您可能已经注意到,本段可以应用更多的机制.因此,尽管不需要这样做,但GCC和Clang的前端可能需要更加努力地工作,因此能够对它进行诊断.

Again, a "shall" requirement, and it says explicitly that no diagnostic is required. As you may have noticed, there's quite a bit more machinery that this paragraph can apply to. So the front ends for GCC and Clang probably need to work harder, and as such are able to diagnose it, despite not being required to.

该程序格式不正确.

MM

As M.M pointed out in a comment, the C standard has an informative section that mentions the very extension in zwol's answer.

J.5.11多个外部定义

对于以下标识符,可能有多个外部定义 一个对象,无论是否显式使用关键字extern;如果 定义不同意,或者不止一个被初始化, 行为是不确定的(6.9.2).

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).

这篇关于在C和C ++中不使用extern的不同编译结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆