【问题标题】:C to C++ table inline definitionC 到 C++ 表内联定义
【发布时间】:2018-11-08 00:37:12
【问题描述】:

我有可以正确编译和工作的 C 代码,我想在 C++ 中使用类似的代码:

static const char* aTable[12] = {
    [4]="seems",
    [6]=" it  ",
[8]="works",};

int main(){
    printf("%s%s%s", aTable[4],aTable[6],aTable[8]); 
    return 0;
}

现在,如果我将它放在 .c 文件中并使用 gcc 进行编译,它就可以工作。但是,如果我把它放在一个.cpp 文件中并用g++ 编译它,我会得到以下错误:

test_cpp.cpp:5:3: error: expected identifier before numeric constant
test_cpp.cpp:5:4: error: type '<lambda>' with no linkage used to declare function 'void<lambda>::operator()() const' with linkage [-fpermissive] 
test_cpp.cpp: In lambda function: test_cpp.cpp:5:5: error: expected '{' before '=' token 
test_cpp.cpp: At global scope: test_cpp.cpp:5:5: warning: lambda expressions only available with
    -std=c++0x or -std=gnu++0x [enabled by default] 
test_cpp.cpp:5:6: error: no match for 'operator=' in '{} = "seems"' test_cpp.cpp:5:6: note: candidate is: test_cpp.cpp:5:4: note: <lambda()>&<lambda()>::operator=(const<lambda()>&) 
test_cpp.cpp:5:4: note:   no known conversion for argument 1 from 'const char [6]' to 'const<lambda()>&' 
test_cpp.cpp:6:3: error: expected identifier before numeric constant
test_cpp.cpp:6:4: error: type '<lambda>' with no linkage used to declare function 'void<lambda>::operator()() const' with linkage [-fpermissive]

有没有办法表示我没有声明 lambda 函数,只是想填一张表?

我想保留以下部分:

[4]="seems",
[6]=" it  ",
[8]="works",

因为它来自自动生成的文件...

【问题讨论】:

  • 还记得 C 和 C++ 是不同的语言吗?即使对于历史版本的编译器也存在一些不兼容问题,那么对于最近编译器的现代扩展来说,问题是最糟糕的。
  • 或者用现代C编译器编译那个文件并链接。
  • 很少有 c 和 c++ 标签都在主题上。最重要的是,这很好地表明,与常见的误解相比,c++ 不是 c 的超集。多么好的问题:)
  • 看起来这将在 C++20 中被允许......
  • @aschepler 我认为 C++20 提案仅适用于 .name = value,而不是 [index] = value。

标签: c++ c gcc g++


【解决方案1】:

您可以轻松混合 C 和 C++ 代码。

您应该保留要使用 C 编译器 (gcc) 编译的 C 代码,其余代码可以是 C++ 并使用 C++ 编译器 (g++) 编译。然后将所有对象 (.o) 文件链接在一起。

像这样:

文件名:a.c

const char* aTable[12] = {
    [4]="seems",
    [6]=" it  ",
[8]="works",};

文件名:b.cpp

#include <cstdio>
extern "C" const char* aTable[12];   
int main(){
    printf("%s%s%s", aTable[4],aTable[6],aTable[8]); 
    return 0;
}

现在编译:

gcc -c a.c -o a.o
g++ -c b.cpp -o b.o
g++ b.o a.o -o all.out

现在运行可执行文件 (all.out),您会发现一切正常。

请注意,对于函数,您需要在 cpp 文件中的声明之前添加 extern "C"。

【讨论】:

  • 这也应该是extern "C" const char* aTable[12];:IIRC 至少有一个编译器会执行名称修改。
  • @hvd 在 g++\gcc 中(两者都被标记在问题中)它可以在没有 extern "C" 的情况下工作,我试图让它尽可能简单。
  • 奖励:生成表格后,无论如何它肯定是一个自己的文件
  • @SHR 最好在保持简单的同时尽可能保持正确。
  • 好的,我已经添加了extern "C"。
【解决方案2】:

没有办法做到这一点。 C++ 从未采用这种特殊的 C 语法。

在您的情况下,由于该表是自动生成的,因此我会将其放在 C 文件中。只要不标记static,就可以从C++代码中毫无问题地访问。

【讨论】:

    【解决方案3】:

    [4]= 是一个指定初始化器,它是 C++ 不支持的 C 特性之一。

    这是一个list,它试图列出 C++17 支持的 C99 功能。向下滚动到底部以查看哪些不受支持。

    重要的是要认识到 C++ 绝不是 C 的超集。

    【讨论】:

    • C 和 C++ 是两种语言,由共同的语法分隔。
    【解决方案4】:

    已经提到过 C++ 不支持的指定初始化器——如果你坚持使用 C++,你可以编写一个带有构造函数的包装类:

    class Table
    {
        std::array<char const*, 12> data;
    public:
        Table()
        {
            data[4] = "seems";
            data[6] = " it  ";
            data[8] = "works";
        }
        char const* operator[](unsigned int index) const
        {
            return data[index];
        }
    } aTable;
    

    没有测试代码,所以如果你发现了一个错误,请随时自己修复它......

    【讨论】:

      【解决方案5】:

      如上所述,C++ 不支持这种类型的初始化,但您可以使用 lambda 函数来初始化 static array&lt;const char*, 12&gt;,如下所示:

      #include <array>
      #include <cstdio>
      
      static const std::array<const char*, 6> aTable = []() {
          std::array<const char*, 6> table;
          table[0] = "Hello";
          table[3] = ", ";
          table[5] = "world!";
          return std::move(table);
      }();
      
      int main() {
          printf("%s%s%s\n", aTable[0], aTable[3], aTable[5]);
          return 0;
      }
      

      Demo on coliru

      值得注意的是,该编译器将在此处执行RVO,并且将就地执行初始化。这是g++-5.4.0生成的程序集:

      <_GLOBAL__sub_I_main>:
      movq   $0x40064c,0x200bc5(%rip)        # 601060 <_ZL6aTable>
      movq   $0x400652,0x200bd2(%rip)        # 601078 <_ZL6aTable+0x18>
      movq   $0x400655,0x200bd7(%rip)        # 601088 <_ZL6aTable+0x28>
      retq   
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-01
        • 2011-08-03
        • 2021-10-28
        相关资源
        最近更新 更多