代码之家  ›  专栏  ›  技术社区  ›  Ryan Maguire

在C++源代码中使用restrict关键字包含C99代码

  •  1
  • Ryan Maguire  · 技术社区  · 11 月前

    我们使用 extern "C" { ... } 包括 C 中的头文件 C++ 。如果 C 文件用途 C99 关键字,如 restrict 例如:

    测试。h

    #ifndef TEST_H
    #define TEST_H
    
    extern void test(int * restrict x, const int * restrict y);
    
    #endif
    

    测试。c

    #include "test.h"
    
    int main(void)
    {
        int n = 1;
        int m = 2;
        test(&n, &m);
        return 0;
    }
    

    test.cpp

    extern "C" {
    #include "test.h"
    }
    
    int main(void)
    {
        int n = 1;
        int m = 2;
        test(&n, &m);
        return 0;
    }
    

    如果我们逃跑 gcc -Wall -Wextra -Wpedantic test.c -c clang -Weverything test.c -c ,编译过程是静默完成的,没有错误或警告。然而 g++ test.cpp -c 导致错误。同样地, clang++ test.cpp -c 失败。

    问题: 有便携的使用方法吗 C99 在头文件中包含(或更高)关键字,然后包含该头文件以供使用 C ?各种 C 图书馆利用 限制 关键字,并且似乎希望能够在 C 图书馆。作为一个简单的例子 C 版本 memcpy (我知道 C 版本 memcpy 不使用 限制 当然,但这是一个足够简单的例子): https://en.cppreference.com/w/c/string/byte/memcpy

    请注意: 存在不可移植的解决方案。例如:

    #if defined(__GNUC__) || defined(__clang__)
    // GCC or clang
    #define restrict __restrict__
    #else
    // MSVC
    #define restrict __restrict
    #endif
    

    或者类似的东西。我正在寻找便携式、符合标准的解决方案。

    1 回复  |  直到 11 月前
        1
  •  6
  •   Eric Postpischil    11 月前

    第一, restrict 参数对非定义的函数声明没有影响。限定符仅适用于左值,对函数的调用将参数作为明文值传递。只有在函数定义中,参数对象才能有限定符。C 2024 6.7.7.4规定:

    在确定类型兼容性时 对于复合类型,每个用限定类型声明的参数都被视为具有其声明类型的非限定版本

    因此,如果你想在C++文件中包含一个标头(仅声明,没有函数定义),你可以简单地抑制 限制 关键字,如:

    #if __cplusplus
        #define restrict
    #endif
    

    ( 限制 如果函数声明在参数内部而不是直接在参数上,则可能在函数声明中产生影响,如 void foo(int * restrict *p); 我从未在代码中见过这种用法。如果它以这种方式存在,它将使C++更改的函数声明与C定义不兼容。)

    其次,即使在函数定义中 限制 是促进优化。删除 限制 从正确的程序中保持正确的程序 _Generic 例外情况如下。C 2024 6.7.4.1规定:

    预期用途 限制 限定符(如 register 存储类)是为了促进优化,从组成一致性程序的所有预处理翻译单元中删除限定符的所有实例不会改变其含义(即可观察的行为),除非 _通用 用于区分类型是否具有该限定符

    我引用了C 2024,但从C 1999开始也是如此,除了没有 _通用 1999年C。