如何更新具有兼容性的C/C++结构

struct在历史图书馆中定义了一个遗憾的类型:unsigned char *而不是char*.

struct MyStruct {

  unsigned char * myMember;
};

struct被大量的 C 应用程序使用,并且越来越多地被 C++ 应用程序使用。这些 C++ 应用程序在与 一起使用时会引发错误strlen,例如,强制我们进行强制转换。很多演员。

我想解决这个问题。

但是有一点非常重要:它必须绝对兼容,无需修改,对现有项目没有影响。

我想过制作一个union. 唉,我的变量不能同名。

struct MyStruct {

  union {
    unsigned char * myMember;
    // char * myMember; Obvioulsy, rejected by the compiler.
};

恐怕没有任何明显的解决方案。我错了吗?

我无法更改结构的大小,因为它映射到大小不变的共享内存中。

回答

注意:你不能在 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

测试代码:

struct MyStruct ms;  
_Generic(ms.myMember, 
         char*:           puts("I'm a char*"), 
         unsigned char*:  puts("I'm an unsigned char*"));

没有#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));
}

  • @AdrianMole Adding functions to `std` namespace is not allowed.
  • You'd have to do this for _all_ string handling functions not just strlen. Quite tedious.

回答

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));

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
};

Fortunately, char is allowed to alias anything in C++, making this legal.


以上是如何更新具有兼容性的C/C++结构的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>