简体   繁体   English

C ++'替换'具有灵活数组成员的结构

[英]C++ 'substitute' for structure with a flexible array member

Consider the following C99 structure, ending with a flexible array member: 考虑以下C99结构,以灵活的数组成员结束:

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: 例如, len使用内联函数(将被放入头文件)访问,像这样,将buf作为其参数:

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. 这是库的一部分,用C编译器编译。 However, I would like to access this library from C++; 但是,我想从C ++访问这个库; this essentially means that the corresponding header file (with proper extern "C" {...} guard) must be valid C++ code. 这实际上意味着相应的头文件(具有适当的extern "C" {...} guard)必须是有效的C ++代码。 A possible solution is to define the slen function in the source code body, avoiding inline code completely, but this is not optimal. 一种可能的解决方案是在源代码体中定义slen函数,完全避免内联代码,但这不是最优的。

My idea is to define a dummy C++ structure that is valid, and that I can map somehow to hdr , eg 我的想法是定义一个有效的虚拟C ++结构,并且我可以以某种方式映射到hdr ,例如

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 ; 请注意,我只想获得lenfree正确(负)偏移值; no access to buf is intended. 不打算访问buf

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? 工作,给出相同的结果?

In the formal nothing is guaranteed, because C++ doesn't support flexible arrays: there is no such thing, no such syntax. 在形式上没有任何保证,因为C ++不支持灵活的数组:没有这样的东西,没有这样的语法。

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 eg 666 instead of 1, which works better in the more general case (eg a small array of 1 char might be moved into some otherwise padding area in some other struct). 然而,为了使这一点非常明确,我将使用例如666而不是1的数组大小,这在更一般的情况下更好地工作(例如,在一些其他结构中,一个小的1个char数组可能被移动到一些否则填充区域) 。 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. 所有这些说,它确实听起来像一个16位Windows BSTR ,除了BSTR在长度和字符串数据之间没有这个差距。 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. 如果是这样,我建议改用原车轮。

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. 如果您正在使用特定的编译器,则可以使用调试器并调整该编译器的偏移量计算并在开始时进行断言,以确保在以后您决定转移到其他编译器或更新版本时,您的假设(调整)仍然成立。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM