C vs C++编译不兼容 - 不命名类型

San*_*der 51 c c++ gcc g++

我正在尝试将供应商的库与我的C++应用程序结合使用.该库主要基于C,这通常不是extern "C"选项的问题,但我遇到了C++编译器不接受的问题.

我将我的代码简化为以下示例文件.header.h表示来自suppier库的头文件,main.c/cpp是我自己的文件.我真正的应用程序是一个C++应用程序,所以我想让它与main.cpp一起使用.

header.h(注意这一行u64 u64;):

#ifndef HEADER_H
#define HEADER_H

#include <stdint.h>

typedef uint64_t u64;

union teststruct {
    u64 u64;
    struct {
        u64 x:32;
        u64 y:32;
    } s;
};

#endif
Run Code Online (Sandbox Code Playgroud)

main.c中:

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

int main() {
    union teststruct a;
    a.u64=5;
    printf("%x\n", a.u64);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

main.cpp(与main.c相同,但有一个额外的extern "C"声明):

#include <stdio.h>

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

int main() {
    union teststruct a;
    a.u64=5;
    printf("%x\n", a.u64);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用该行编译main.c.

gcc -o test main.c
Run Code Online (Sandbox Code Playgroud)

编译没有问题.但是,使用带有命令的g ++编译器编译C++版本

g++ -o test main.cpp
Run Code Online (Sandbox Code Playgroud)

给出以下编译器错误:

In file included from main.cpp:12:0:
header.h:11:9: error: ‘u64’ does not name a type
         u64 x:32;
         ^
header.h:12:9: error: ‘u64’ does not name a type
         u64 y:32;
         ^
Run Code Online (Sandbox Code Playgroud)

问题是供应商对类型和变量名称使用相同的名称(u64),这似乎是一个坏主意,但gcc显然接受它.我不想更改库(即header.h)因为它非常大,这在代码中发生了很多,我偶尔会得到它的更新.有没有办法让g ++接受这种组合,或者修改main.cpp以使其编译而不改变header.h的方法?

Sto*_*ica 48

teststruct用C++定义一个范围.您可以形成合格的ID teststruct::u64.因此,名称查找的语言规则考虑到了这一点,允许类和联合的成员隐藏外部作用域中的标识符.一旦u64 u64;介绍,不合格的u64不能指全球::u64,只指会员.该成员不是一个类型.

在C union teststruct中没有定义范围.该字段只能用于成员访问,因此永远不会出现冲突.因此,该字段不需要隐藏文件范围类型标识符.

据我所知,没有什么可以做的,以便轻松解决它.该库(它是一个完全有效的C库)不是有效的C++库.没有什么不同,如果它使用newtry作为变量名称.它需要进行调整.

  • @Rakete1111:简单来说,C编程需要一种**非常不同的方法(我甚至会说完全不同的*心态*)而不是C++.在某种程度上,我很乐意承认我对C++非常擅长但在C上相当糟糕,尽管我可以写两个.当你第一次学习时,这并不明显,所以我之所以提到这一点 - 如果你假设这些语言中的两段代码应该彼此相似,那么你之后的某些时候你只会撞到墙上(也许)早点,也许晚点).我忘记了你曾经认识C并且从头开始的想法. (4认同)

Max*_*hof 39

看来你有一个在C++中是非法的头文件,所以你不能#include在编译为C++的代码中使用它.如果您无法对库头文件进行更改(例如,向您的库供应商抱怨),那么最直接的选择是在库周围编写一个与C++兼容的瘦包装:

为了隔离对C头你的C++代码,创建一个Wrapper.hWrapper.c,其中.h有效纳入C++,并没有包括header.h,并提供了你需要的库交互的所有类型和功能.然后,在中.c,您可以#include "header.h"实现所有调用(以及您需要做的任何事情以安全地在类型之间进行转换).这显然必须编译为C,而不是C++.

  • 这种方法的缺点是,除非您正在进行链接时优化,否则会为每个库调用添加额外的过程调用开销层. (4认同)