`char * const` 字段被 MSVC (VS2015) 考虑 "incompatible with C"

`char * const` field considered "incompatible with C" by MSVC (VS2015)

我有以下代码在 VS2015 中编译时没有警告(启用所有警告):

// buffer.h

typedef struct {
    char * const start; // start of the buffer
    char * const end;   // one byte after the end of the buffer
    char * pos;         // current position
} Buffer;

static inline Buffer Buffer_create(char *buffer, int size) {
    Buffer b;

    char ** const startPtr = &((char *)b.start);
    char ** const endPtr = &((char *)b.end);

    *startPtr = buffer;
    *endPtr = buffer + size;
    b.pos = buffer;

    return b;
}

由于 .start.end 成员是 const,我正在做强制转换以避免收到编译警告,并且代码确实在没有警告的情况下编译并且没有问题。

但是,如果我想使用 gtest 对此进行测试,并且如果我想从 .cpp 文件中引用此文件:

// some_file.cpp

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

我从 Visual Studio 得到 C4190 warning,描述为:

'Buffer_create' has C-linkage specified, but returns UDT 'Buffer' which is incompatible with C

但是 UDT 显然是 "compatible with C",因为我可以在没有警告的情况下构建它,直到我尝试从 cpp 文件中引用它。

如果我从 struct 定义中删除 const,警告就会消失。

所以,MSVC 似乎认为 char * const 不是 "compatible with C"。我是在做违法的事情,还是编译器错误?

根据 the documentation you linked 的警告 C4190,不支持具有 returns 按值 struct 从 C 和 C++ 调用的函数。

(在 C++ 标准中,语言混合的大部分细节都是作为实现定义的,在这种情况下,MSVC 通过记录不支持来遵守)。

我也不建议在编译为 C 和 C++ 的头文件中使用 inline 函数,因为 inline 的语义在两种语言之间不同,所以它会带来麻烦.

如果您想在两种语言中使用 Buffer_create,则必须对设计进行重大更改才能避免此问题。例如,"return" 通过指针输出参数的结果,并取消 const 结构成员。

您确定结构定义吗?将成员定义为 const 没有多大意义,而是将指针定义为 const char *char const * 是等效的:

typedef struct {
    char const *start; // start of the buffer
    char const *end;   // one byte after the end of the buffer
    char * pos;        // current position
} Buffer;

在 C 和 C++ 上下文中尝试这个定义。

如果您打算在结构中使用常量指针,则可以在 Buffer_create 函数中使用初始化程序,而不是这些丑陋的强制转换:

static inline Buffer Buffer_create(char *buffer, int size) {
    Buffer b = { buffer, buffer + size, buffer };
    return b;
}