【问题标题】:Visual studio C compiler not linking header file to its source counterpartVisual Studio C 编译器未将头文件链接到其源对应文件
【发布时间】:2015-04-03 15:43:16
【问题描述】:

我正在使用 VS 并在 C 中使用我的第一块可重用代码,因此我将我的代码分成头文件和源文件,这会导致一些意外行为。

在我看来,不知何故,链接器无法解析我的 typedef 结构。我尝试将实际的结构声明移动到实现文件中,并从头文件中对结构进行类型定义,但没有成功。

为了简洁起见,我删除了所有实现,因为这不是问题。

// queue.h
#ifndef INC_QUEUE_
#define INC_QUEUE_

#include <stdint.h>

// STRUCT TYPEDEF
typedef struct QueueElement { ... } QueueElement;
typedef struct Queue { ... } Queue;

// FUNCTION PROTOTYPES
Queue* queue_construct();
uint32_t queue_peek(Queue *);
void queue_enqueue(Queue *, uint32_t);
uint32_t queue_dequeue(Queue *);
uint8_t queue_empty(Queue *);
void queue_destroy(Queue *);

#endif


// queue.c
#include <stdlib.h>
#include "queue.h"

Queue* queue_construct() { ... }
uint32_t queue_peek(Queue *queue) { ... }
void queue_enqueue(Queue *queue, uint32_t element) { ... }
uint32_t queue_dequeue(Queue *queue) { ... }
uint8_t queue_empty(Queue *queue) { ... }
void queue_destroy(Queue *queue) { ... }

源代码一切正常,都可以编译,但是当我尝试将其包含在例如这个文件...

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

int main()
{
  Queue *q = queue_construct();
  queue_destroy(q);
  return 1;
}

我的链接器一直给我的错误:

error LNK2019: unresolved external symbol "struct Queue * __cdecl queue_construct(void)" (?queue_construct@@YAPAUQueue@@XZ) referenced in function _main
error LNK2019: unresolved external symbol "void __cdecl queue_destroy(struct Queue *)" (?queue_destroy@@YAXPAUQueue@@@Z) referenced in function _main

任何帮助将不胜感激,这可能是一个愚蠢的问题,但正如我所说,我从未在 VS C 中处理过“更大/多文件”项目。

编辑
有人向我指出,包含 main 函数的源文件确实在 cpp 源文件中,但我的头文件和实现在 C 文件中。据我所知,您可以在 C++ 代码中的任何位置使用 C 文件,其中一个示例就是能够在 C++ 中使用任何 C 系统库。

该程序现在运行良好,但现在我的问题是:为什么我不能在 cpp 文件中使用 C 头文件?为什么会出现这种情况。显然我错过了一些重要的东西。

【问题讨论】:

  • 似乎无法找到 queue.c 中的函数。你确定这个文件是你项目的一部分并且是和 main.c 一起构建的吗?
  • 我会这么说。我有一个项目,其中包含 VS 为给定 C++ 项目创建的默认文件夹,我的 *.h 文件位于“头文件”文件夹中,源文件位于“源文件”文件夹中。
  • 我看到的唯一一件事是结构名称和 typedef 是相同的。尝试将typedef struct Queue { .... } Queue; 更改为typedef struct queue_ { ....} Queue; 我很难相信这是原因,但这是我唯一能看到的。这是假设 main.c 和 queue.c 都被编译和链接在一起。注:早在上个世纪(大约 1983 年),当我学习 C 时,有人告诉我要确保名称不同……不记得解释了,我只是一直这样做。
  • 名称应该不同的原因是(回到何时)编译器内只有一个命名空间。现代编译器在跟踪具有相同名称拼写的不同关联方面要好得多。但是,结构定义应该有一个标签名称,而没有 typedef 名称。那么对结构定义的所有引用都应该是“struct tagName”。使用 struct tagName 在几个方面有帮助:代码更清晰/没有不必要/误导性的名称,编译器名称空间没有多余的条目,它是首选语法
  • 看起来队列文件是用C编译的,主文件是用C++编译的

标签: c visual-studio struct header linker


【解决方案1】:

在一些 cmets 的帮助下,问题是我的主程序是在一个 cpp 文件中编写的,并且包含了我自己的 c 头文件。愚蠢的是,我不知道您不能简单地在 C++ 中使用 C 库。

简单地将主文件转换为 C 源文件即可解决问题。

这不是我需要的,因为我需要我的源文件在 C++ 中,所以只需搜索一下,解决方案很简单。我只需要像这样更改我的主要 cpp 源文件:

// main.cpp
#include <stdio.h>

extern "C" {
  #include "queue.h"
}

int main()
{
  Queue *q = queue_construct();
  queue_destroy(q);
  return 1;
}

希望这可以防止其他人犯我犯的同样幼稚的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 2016-07-24
    • 1970-01-01
    相关资源
    最近更新 更多