【问题标题】:Why do I get "undefined reference"-error with a variable marked as 'extern'? Linker problem? [duplicate]为什么我会收到带有标记为“extern”的变量的“未定义引用”错误?链接器问题? [复制]
【发布时间】:2019-09-20 22:16:58
【问题描述】:

我知道这个问题已经被问过好几次了(以类似的方式),但我不认为这是重复的,因为我的代码已经实现了提供给其他提问者的解决方案。如果我忽略了某些内容,我的问题当然可能会被标记为重复并降级。

我必须使用外部变量,因为根据任务,我不允许将其作为参数传递。问题:如果我想编译代码,就会抛出“未定义的引用”-错误​​。

代码:

header.h

#ifndef TEST_HEADER_H
#define TEST_HEADER_H

extern int var;

void increment();

#endif //TEST_HEADER_H

source1.c

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

int main ()
    {
        int var = 1;
        printf("1) %d\n", var);

        increment();
        printf("2) %d\n", var);

        return 0;
    }

source2.c

#include "header.h"

void increment()
    {
        var++;
    }

编译错误:

====================[ Build | test | Debug ]====================================
/root/clion-2019.1/bin/cmake/linux/bin/cmake --build /root/CLionProjects/test/cmake-build-debug --target test -- -j 2
Scanning dependencies of target test
[ 33%] Building C object CMakeFiles/test.dir/source1.c.o
[ 66%] Building C object CMakeFiles/test.dir/source2.c.o
[100%] Linking C executable test
/usr/bin/ld: CMakeFiles/test.dir/source2.c.o: in function `increment':
/root/CLionProjects/test/source2.c:5: undefined reference to `var'
/usr/bin/ld: /root/CLionProjects/test/source2.c:5: undefined reference to `var'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/test.dir/build.make:100: test] Fehler 1
make[2]: *** [CMakeFiles/Makefile2:73: CMakeFiles/test.dir/all] Fehler 2
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/test.dir/rule] Fehler 2
make: *** [Makefile:118: test] Fehler 2

CMakeLists.txt:

cmake_minimum_required(VERSION 3.14)
project(test C)

set(CMAKE_C_STANDARD 11)

add_executable(test source1.c header.h source2.c)

我还尝试将以下内容添加到 CMakeLists.txt,因为它有助于解决“未定义引用”错误的另一种情况,但在这种情况下没有区别。

find_library(LIBRT rt)
if(LIBRT)
    target_link_libraries(test ${LIBRT})
endif()

我认为问题不在于代码,是吗?我认为这是在链接过程中。有人可以帮忙吗?提前致谢!

编辑:

它现在运行。我的问题不在于我无法区分声明和定义,正如一些人认为的那样,而是我将'source1.c'中的定义设置在'main'(本地)而不是外部(全局)内的错误位置。所以,准确地说,我的误解是估计外部声明与其定义之间的范围,如果你明白我的意思的话。诚然,这不是天才的一击。 ;-) 谢谢您的帮助!

【问题讨论】:

  • 您应该多花点时间了解一下作用域。你声明了一个 global 变量,但是你定义了一个 local 变量。
  • 在某处定义var 怎么样?

标签: c cmake linker extern undefined-reference


【解决方案1】:

这个

extern int var; /* declaration, it doesn't exist until its not defined somewhere */

只是一个声明,你需要定义它。由于您没有为var 提供定义,链接器无法找到它,因此出现错误

对 `var' 的未定义引用

注意source1.c

int var = 1;

它不是extern 变量的定义,它是一个本地创建的具有功能范围的变量。

【讨论】:

    【解决方案2】:

    您误解了extern 的含义。

    将变量(或函数)标记为extern 不会定义(创建)该变量。相反,它只是声明它存在于某个地方。您在任何地方都没有var 的定义。

    在您的main 中有int var = 1;,但该定义是本地main。它不是全局的,任何其他功能都无法访问。

    您应该将该变量定义移出main

    #include <stdio.h>
    #include "header.h"
    
    int var = 1;
    
    int main ()
    {
        printf("1) %d\n", var);
    
        increment();
        printf("2) %d\n", var);
    
        return 0;
    }
    

    在相关说明中:您应该避免使用全局变量。它们导致代码难以理解、调试和维护。

    【讨论】:

    • Quib​​ble:仅仅声明一个变量 extern 并没有定义它或导致它被定义,是的,但是 extern 声明确实可以作为一个定义,如果它包括一个初始化程序。
    • @John 啊,是的,我忘记了那个案子。我从不使用它,因为它感觉很矛盾。
    • 我同意。显式声明变量extern 的目的通常是避免将该声明用作定义,因此通过提供初始化程序来克服这一点有点奇怪。但它也符合相关的语言特征。我认为真正奇怪的是,显式声明一个对象具有默认情况下具有的属性会有所不同。
    • @JohnBollinger 我想这有点奇怪,但extern 是一个存储类说明符,因此不允许在带有初始化程序的定义中使用它也会很奇怪,即使在实践中,它的主要使用是为了避免将外部变量声明变成暂定定义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-23
    • 2014-03-31
    • 2016-09-10
    相关资源
    最近更新 更多