Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ 'substitute' for structure with a flexible array member

Consider the following C99 structure, ending with a flexible array member:

struct hdr
{
  size_t len;   
  size_t free;  
  char buf[];
};

len, for example, gets accessed with an inline function (to be put into a header file) like this, having buf as its argument:

static inline size_t slen(const char *s)
{
  struct hdr *h = (struct hdr*)(s - (int)offsetof(struct hdr, buf));
  return h->len;
}

This is part of a library, to be compiled with a C compiler. However, I would like to access this library from C++; this essentially means that the corresponding header file (with proper extern "C" {...} guard) must be valid C++ code. A possible solution is to define the slen function in the source code body, avoiding inline code completely, but this is not optimal.

My idea is to define a dummy C++ structure that is valid, and that I can map somehow to hdr, e.g.

struct cpp_hdr
{
  size_t len;
  size_t free;
  char buf[1];
}

Note that I only want to get correct (negative) offset values for len and free; no access to buf is intended.

Now my question: Is there any guarantee that

static inline size_t slen(const char *s)
{
  struct cpp_hdr *h = (struct cpp_hdr*)(s - (int)offsetof(struct cpp_hdr, buf));
  return h->len;
}

works, giving the same result?

like image 623
lemzwerg Avatar asked Sep 17 '14 13:09

lemzwerg


Video Answer


2 Answers

In the formal nothing is guaranteed, because C++ doesn't support flexible arrays: there is no such thing, no such syntax.

In practice compilers don't do things for no direct reason. So there won't be any willy-nilly padding introduced. However, just to make that abundantly clear I would use an array size of e.g. 666 instead of 1, which works better in the more general case (e.g. a small array of 1 char might be moved into some otherwise padding area in some other struct). As a benefit, clever code for allocation won't look simple any more. So that that has to be done properly.

All this said, it sure sounds like a 16-bit Windows BSTR, except a BSTR doesn't have that gap between the length and the string data. Consider whether this library is just someone's for no good reason reinvention of the wheel. If so, I suggest using an original wheel instead.

like image 152
Cheers and hth. - Alf Avatar answered Oct 10 '22 16:10

Cheers and hth. - Alf


Assuming library was compiled by a different compiler, it is not guaranteed that offset would be same. Practically, it should work most of the time.

If you are working on a specific compiler, you can use debugger and tune your offset calculation for that compiler and make an assertion in beginning to ensure your assumption (tuning) still holds true if later you decide to move to a different compiler or newer version.

like image 2
Mohit Jain Avatar answered Oct 10 '22 14:10

Mohit Jain