开发者

Can I safely replace a bool member with unsigned char in a public header?

I ship a public header that users compile against to utilize classes contained within. I need to fix an issue in the shared library that implements one of these public classes and have a requirement that existing users need not recompile their libraries when installing a patch. The fix requires a bool member to be able to hold more information than false,true. The class looks like

class PublicAPI{
...
public:
  bool getSync();
  void setSync(bool sync);
...
private
  bool sync_;
...
};

I'd like to change bool sync_; to unsigned char sync_;:

class PublicAPI{
...
public:
  bool getSync();
  void setSync(bool sync);
...
private
  unsigned char sync_;
...
};

Note that the getters and setters won't and I don't think can change. They will be ok, since the user will not need to be aware of the additional values sync_ contains and I will handle retaining my values internall开发者_如何转开发y. Obviously this is an ugly hack, but I think technically it's ok because the size of the class won't change.

My concern is that a compiler on one of the platforms I ship on Linux, AIX, HPUX, Solaris, Windows will play some game with the bool type I'm not aware of and break something.

Any thoughts on how safe or dangerous this is?


I don't think there's a way to do what you want that's guaranteed to be safe. Some compiler might have different sizes for bool and unsigned char.

It seems pretty unlikely that this would be the case on most compilers and you can probably get away with it. Better of course is to "suggest" a recompile but allow that it may work without recompiling.

This is a perfect example where pimpl'ing your implementation would have eliminated any concern as the internal type would have been fully hidden within your library rather than expost.


I don't know about GCC, but I did some similar hacks with MSVC 6 a long time ago (most of them were replacing a DWORD with a pointer). Worked just fine. Of course, as many others already wrote, sizeof(whateverYouUse) must equal sizeof(bool). That shouldn't be a problem though, since you can always use

class PublicAPI{
...
public:
  bool getSync();
  void setSync(bool sync);
...
private
  unsigned char sync_[sizeof(bool)];
...
};

And then use sync_[0] internally.


The safest way would be to use a union of bool and unsigned char. When bool is larger than char, the union would be aligned like a bool, but still contain the char.

Both bool and char are POD types, so there is no big deal. All access is via the two non-inlined members (you are sure they're not inline? I.e. not defined inside the class?) which means you always access the union via the char member.


I'm pretty sure that technically, you'd invoke undefined behaviour. However, I think that in practicality no compiler will throw on that change.


Technically, it's undefined behavior, and in practice, it almost certainly won't work---the function names will be mangled (decorated) differently, and the linker will fail to find the function.

In most such cases, the solution is to override, with the old function forwarding to the new one, e.g.

public:
    void setSync(bool sync);
    void setSync(int sync);

, with setSync(bool sync) implemented as:

void PublicAPI::setSync(bool sync)
{
    setSync(sync ? 1 : 0);
}

Don't make the new implementation of setSync inline. (If the old one was in fact inline, you're screwed.)


if sizeof(bool)!=sizeof(char) and because of this the size of the class will be different. This may cause you troubles if you have a module that is compiled with an old header and have a new binary. To avoid compiling issues, just be sure you cast and should be ok.


You don't need to change the header file at all, if you can bring yourself to program like this:

#include <iostream>
using namespace std ;

static bool b ;
int main()
  {
  unsigned char u0 = 99 ;
  *reinterpret_cast<unsigned char*>(&b) = u0 ;
  unsigned char u1 = *reinterpret_cast<unsigned char*>(&b) ;
  cout << int(u1) << endl ;
  }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜