`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;
}
我有以下代码在 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;
}