bit*_*kid 16 c c++ compatibility casting
我struct
在历史图书馆中定义了一个遗憾的类型:unsigned char *
而不是char*
.
struct MyStruct {
unsigned char * myMember;
};
Run Code Online (Sandbox Code Playgroud)
这struct
被大量的 C 应用程序使用,并且越来越多地被 C++ 应用程序使用。这些 C++ 应用程序在与 一起使用时会引发错误strlen
,例如,强制我们进行强制转换。很多演员。
我想解决这个问题。
但是有一点非常重要:它必须绝对兼容,无需修改,对现有项目没有影响。
我想过制作一个union
. 唉,我的变量不能同名。
struct MyStruct {
union {
unsigned char * myMember;
// char * myMember; Obvioulsy, rejected by the compiler.
};
Run Code Online (Sandbox Code Playgroud)
恐怕没有任何明显的解决方案。我错了吗?
我无法更改结构的大小,因为它映射到大小不变的共享内存中。
Lun*_*din 10
注意:你不能在 C++ 中解决这个问题,因为严格的 C 也不喜欢unsigned char*
。即使使用宽松的 C 编译器设置,您也会得到(gcc 默认设置的示例):
赋值中的指针目标的符号不同 [-Wpointer-sign]|
即使在做一些基本的事情,比如简单的赋值ms.myMember="hello";
。
这是一个 C11 解决方案。
struct MyStruct {
union // anonymous union
{
unsigned char * myMember;
char* myCharMember;
};
};
#define myMember myCharMember
Run Code Online (Sandbox Code Playgroud)
测试代码:
struct MyStruct ms;
_Generic(ms.myMember,
char*: puts("I'm a char*"),
unsigned char*: puts("I'm an unsigned char*"));
Run Code Online (Sandbox Code Playgroud)
没有#define
和 它会告诉你"I'm an unsigned char*"
,但是有了#define
, "I'm a char*"
。
有一个更简单的补救措施。通常,当你对某件事做太多次而感到恼火时,可以简单地通过在函数内做一次那件事来解决:
std::size_t unsigned_strlen(const unsigned char* str) noexcept
{
return std::strlen(reinterpret_cast<const char*>(str));
}
Run Code Online (Sandbox Code Playgroud)
There is no way you can make the myMember
be a char*
or any other type without potentially breaking existing projects, for the simple reason that its type can be deduced
void foo(decltype(MyStruct::myMember));
Run Code Online (Sandbox Code Playgroud)
This will cause ABI issues, the mildest of which is a linker error.
The half measure is to provide a shorthand for the cast
struct MyStruct
{
#ifdef __cplusplus
char* signed_myMember() { return (char*)myMember; }
#endif
};
Run Code Online (Sandbox Code Playgroud)
Fortunately, char
is allowed to alias anything in C++, making this legal.
鉴于您的目标是创建一个完美岛而不是修复世界,您可以从这个旧结构创建一个带有隐式构造函数的适配器,并在“完美岛”代码中使用该适配器。
struct BetterMyStruct {
char* myMember;
BetterMyStruct(MyStruct const& x): myMember((char*)x.myMember) {
// any ugly secret hacks you want or need
}
};
...
size_t better_strlen(BetterMyStruct const& x) {
// perfect function
return std::string_view(x.myMember).size();
}
...
better_strlen(MyStruct(...)); // perfect function invocation on imperfect inputs
Run Code Online (Sandbox Code Playgroud)