c++ - extern "C"静态数组函数参数

标签 c++ c c99 c11

我想与我从 C++ 程序编写的 C 库进行交互。 C 库是使用现代 C 编写的,并使用了 static数组说明符以显示数组的最小长度,或者指针不能是 NULL .

当我尝试编写一个与 extern "C" 接口(interface)的程序时使用此功能的功能我收到以下消息:

error: static array size is a C99 feature, not permitted in C++



不能与这个 C 库交互吗?我是否必须修改 C 库,或者是否有替代方案?

这是导致错误的示例程序:
// foo.h

#ifndef FOO_H
#define FOO_H

void foo(int i[static 1]);

#endif //FOO_H
// foo.c
#include <stdio.h>

void foo(int i[static 1]) {
    printf("%i", i[0]);
}
// main.cpp

extern "C"
{
    void foo(int i[static 1]);
}

int main() {
    int i[] = {1};
    foo(i);
}

最佳答案

extern "C"向 C++ 编译器指示函数名称不应被破坏。由于您正在链接外部库,因此期望外部库有一个名为 foo 的函数(并且只有一个函数)。 . static C99 及以后的数组大小中的关键字告诉编译器“这个数组将至少是这个大小”,这可能允许编译器进行某些优化(我不知道这些可能是什么优化,但考虑到它可以可能循环展开到 N = 4 ,您在其中声明了 void foo(int i[static 5]); 如果您传递的数组不是至少这个大小,您可能会遇到麻烦。

直接的解决方案就是我们需要告诉 C++ 编译器:

  • 有一个函数叫做 foo
  • 它需要一个 int *作为参数
  • extern "C"
    {
        void foo(int i[]);
    }
    

    但是我们丢失了在 C++ 程序中使用 this 的任何人的信息,即这个函数的大小必须至少为 N(这就是数组大小中的 static 关键字的含义)。我想不出一个好方法来强制对此进行编译时检查,除非可能通过某种类型的模板化包装函数:
    #include <cstddef>
    
    extern "C"
    {
        void foo(int i[]);
    }
    
    template <std::size_t N>
    void c_foo(int i[N])
    {
        static_assert(N >= 5);
        foo(i);
    }
    
    int main(int argc, char** argv)
    {
        int a[5] = {1, 2, 3, 4, 5};
        int b[4] = {1, 2, 3, 4};
    
        c_foo<5>(a); // this will be fine
        c_foo<4>(b); // this will raise a compile-time error
    }
    
    
    

    为了更加安全,我会为您的 c_foo 放置函数原型(prototype)。功能和任何“安全”extern "C"原型(prototype)合二为一c_library_interface.h文件,以及 c_foo 的函数定义函数和任何“不安全”extern "C"另一个 c_library_interface_unsafe.cpp 中的原型(prototype)文件。那样的话,只要你不在你的主 C++ 文件中包含 unsafe 文件,你应该只能与 static 交互。数组大小函数通过模板,这将做一些大小检查。

    关于c++ - extern "C"静态数组函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60517139/

    相关文章:

    c - Makefile 文件名约定

    c - 重新分配从函数返回的值会产生段错误

    c++ - 反对使用 size_t 的理由是什么?

    c - 在 Visual Studio 中是否有任何选项可以在 C99 和 C11 C 标准之间切换?

    c++ - 手动编码的快速排序在较小的整数上较慢

    c - 仅某些回文被写入文件

    c++ - Boost.Spirit 不解析整个输入

    c - 使用 GCC 在 C 中未定义对 SIGN 的引用

    c++ - rangesv3 ts 中的 "range"和 "view"有什么区别?

    c++ - PutFile 不从事件目录发送文件?