【问题标题】:Error in compiling C code with variable name new with g++使用 g++ 编译具有新变量名的 C 代码时出错
【发布时间】:2014-01-06 08:12:37
【问题描述】:

我们正在尝试修改一些现有的 C 项目,即我们正在尝试从 C 代码进行一些 C++ 函数调用。我们尝试将编译器从 gcc 更改为 g++,但由于不兼容,出现了几个编译错误。我们正在尝试做的是在 C 代码中调用一些 C++ 函数,而不对现有代码进行任何更改。简单地更改编译器似乎并没有解决问题。因此我们尝试了以下操作:

#include <stdio.h>

extern "C"
{
    int func(int new ) {
        printf("in new func()\n");
    }
}

当我使用命令编译它时

g++ -c hello.c -o 你好

我们得到以下错误

hello.c:9: error:expected ‘,’ or ‘...’ before ‘new’.

现在我们知道 new 是 c++ 关键字。如前所述,我们尽量不对现有的 C 代码进行任何修改。有什么建议吗?

这些不是唯一的错误。还有其他与结构声明有关的错误。

attr.c:75: 错误:'.' 标记之前的预期主表达式

在 attr.c,第 75 行是

静态 post_op_attr error_attr = {.attributes_follow = FALSE };

问题是代码中还有其他 C 风格的结构声明和初始化,所以即使我们重命名变量名,我们仍然需要修改 C 程序的其他部分。因此,我们正在寻找一种在不修改现有 C 代码的情况下将 C++ 函数调用添加到 C 代码的方法。

【问题讨论】:

  • 如果你不想对C代码做任何修改,为什么不继续编译成C呢?在 C++ 中,您只需要 extern "C" 声明您需要调用的函数。
  • 为了澄清 Charles 的观点,请注意在 C++ 程序的声明中,您不需要为参数命名。
  • @BoBTFish 在 C 中也没有必要。
  • 致 OP:“使用 g++ 编译 C 代码时出错”——确切地说,这是一个错误。 C 代码只能使用 C 编译器编译,而 g++ 不是,因为它是 C++ 编译器。
  • @H2CO3 是的,但我想指出的是,在您声明它的地方(将在C++ 代码中),您不需要给它一个名字。在定义中,名称是必需的,但这没关系,因为它将在C 代码中。

标签: c++ c gcc g++


【解决方案1】:

从您的 deleted question 迁移。

extern "C" 的作用

extern "C" 不会将该代码视为 C 代码,它只是一个链接选项。

查看this post here on SO 了解更多信息。为了使其简短(简单),它改变了函数名在二进制文件中的存储方式(C++ 编译器修改 - decorate - 由于函数重载而导致的函数名:相同的名称但不同的参数)。只有在将 C 库链接到 C++ 模块时(或从 C++ 模块导出 C 接口时)才需要它。

C 和 C++ 编译器

因为您使用的是 C++ 编译器(g++ 是 C++ GCC 前端,是否感到困惑?看看这篇关于 what's difference between gcc and g++ 的帖子)您的文件将被编译为 C++ 代码并且您不能使用 C++ 关键字(如发布在this answer)。

解决方案

要使用 g++ C++ 前端编译 C 源文件(假设您不能简单地调用 gcc C 前端),您必须使用 -std=c99(有关 C99 GCC 支持,请参阅 this documentation)。

g++ -c -std=c99 hello.c -o hello

【讨论】:

    【解决方案2】:

    C 和 C++ 是不同的语言,所以用 C++ 编译器编译 C 代码没有多大意义。

    但您不必这样做,人们每天都会在不同的编译单元中组合 C 和 C++。只需创建一个公共头文件toto.h,您将在两者中都包含它。将所有函数都包含在 extern "C" 子句中,使 C 不可见而 C++ 可见。

    #ifdef __cplusplus
    extern "C" {
    #endif
    
       // your function declarations (not definitions) go here
    
    #ifdef __cplusplus
    }
    #endif
    

    现在您可以在单独的编译单元(.c 文件)中实现您的功能。而且这些函数可以毫无问题地相互调用。

    【讨论】:

      【解决方案3】:

      C++ 中标识符的规则是:

      1. 只允许使用字母、数字和下划线。

      2.标识符名称不能以数字开头。

      3.Key words cannot be used as a name.
      

      4.大小写字母不同。

      5.不允许使用特殊字符

      6.全局标识符不能用作“标识符”。

      编辑:关于您在不修改 C 代码的情况下从 C 代码调用 C++ 函数的要求,

      一种方法是用 C 语言围绕你的 C++ 代码编写一个包装器,然后用 gcc 编译,这里讨论的直接从 g++ 调用 c 代码并不容易:

      How to call C++ function from C?

      你也可能想看这个:

      http://www.thegeekstuff.com/2013/01/mix-c-and-cpp/

      http://research.engineering.wustl.edu/~beardj/Mixed_C_C++.html

      还有

      http://www.parashift.com/c++-faq-lite/c-calls-cpp.html

      【讨论】:

      • 静态 post_op_attr error_attr = {.attributes_follow = FALSE };错误是: attr.c:75: error: expected primary-expression before '.' token 问题是代码中还有其他 C 风格的结构声明和初始化,所以即使我们重命名变量名,我们仍然会有修改 C 程序的其他部分
      • @Raheel:确实。再多的魔法也无法将 C99 程序变成 C++11。这两种语言在 90 年代初分叉。今天,它们大多是链接兼容的。
      【解决方案4】:

      每种计算机语言都有一些保留关键字,它不允许用作变量名。这是一个 c 语言保留关键字列表,您不应将其用作变量名http://www.tutorialspoint.com/ansi_c/c_reserved_keywords.htm

      在使用 c++ 编译器进行编译时,还应避免使用 c++ 保留关键字,这是 c++ 关键字的链接http://cs.smu.ca/~porter/csc/ref/cpp_keywords.html

      new 更改为其他内容,例如将new 更改为num 或其他内容。

      【讨论】:

        【解决方案5】:

        正如你所说new是C++关键字,所以不能用作变量名。

        如果您的 C 代码正在调用 C++ 函数,那么您应该真正认为它不是 C 或更多,而是 C++。这将意味着更多(如果你想让它成为惯用的 C++,更多,更多),然后只是替换一些命名错误的变量。

        但是,如果您打算对您的 C 代码库进行最小的更改,您可以试试这个技巧:

        #define new new__ 
        

        但是,我真的不建议将其作为长期解决方案。

        【讨论】:

        • 虽然#define 可能适用于大多数编译器,但从标准C++ 的角度来看它是非法的。所以如果你使用这个,你就不会再写C++了(尽管它可能会起作用)。
        • 静态 post_op_attr error_attr = {.attributes_follow = FALSE };错误是: attr.c:75: error: expected primary-expression before '.' token 问题是代码中还有其他 C 风格的结构声明和初始化,所以即使我们重命名变量名,我们仍然会有修改C程序的其他部分
        • @user3114360,嗯,这是一个不同的问题。那些新奇的 C99 结构初始化器不能很好地与 C++ 配合使用。
        • @Roddy 那么有没有与之相关的编译器标志来解决这个问题,或者任何其他解决方案??
        • @BoBTFish 只有在你使用 C++ 标准库时才非法,如果我理解正确的话。 stackoverflow.com/questions/9109377/…
        【解决方案6】:

        new是关键字,如果不想修改代码就不要使用g++。 请改用gcc

        注意:如果是c代码,千万不要包含extern "C",如果是c++代码,千万不要使用new作为变量。

        【讨论】:

        • 静态 post_op_attr error_attr = {.attributes_follow = FALSE };错误是: attr.c:75: error: expected primary-expression before '.' token 问题是代码中还有其他 C 风格的结构声明和初始化,所以即使我们重命名变量名,我们仍然会有修改C程序的其他部分
        【解决方案7】:

        new 是关键字,因此您不能调用变量new。但即使你可以,我也不确定你为什么会这样做,因为它非常难以阅读。

        即使您使用的是extern "C",您仍在使用g++ 进行编译,它是c++ 编译器,它会抱怨这个问题。

        基本上,C 代码在 c++ 中不能始终不变地运行,因为 c++ 引入了一些关键字。在这种情况下,您别无选择,只能更改一些现有代码 C 代码以使其编译为 C++ 代码。

        【讨论】:

        • 抱歉,现在了解
        • 如果我们不使用 c++ 编译器,即 g++,我们将无法在现有 C 代码中使用 C++ 函数。
        • @user3114360 :那是因为 C 是与 C++ 不同的语言。如果您想将您的 C 转换为 C++,那么现在是修复变量名的时候了。
        • @user3114360 我以为您根本不想更改现有的C 代码?如果您仍然要更改它(添加一些对C++ 函数的调用),只需更改名称即可。
        • 答案只是将旧的 C 代码更改为没有任何 c++ 关键字。恐怕你真的别无选择。
        猜你喜欢
        • 1970-01-01
        • 2022-10-02
        • 2015-11-05
        • 1970-01-01
        • 2011-01-22
        • 2023-03-09
        • 1970-01-01
        • 2011-09-16
        • 2016-12-15
        相关资源
        最近更新 更多