Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I 'fill up' remainder of a size at compile time?

Tags:

c++

Let's say I have the following

struct MyType { long a, b, c; char buffer[remainder] }

I wanted to do something like

char buffer[4096 - offsetof(MyType, buffer)]

But it appears that it's illegal

like image 237
Pac Avatar asked Sep 28 '20 01:09

Pac


2 Answers

You can do:

struct ABC {long a,b,c; }
struct MyType : ABC {char buffer[4096-sizeof(ABC)];};
static_assert(sizeof(MyType)==4096,"!");
like image 163
Eugene Avatar answered Oct 27 '22 01:10

Eugene


Your problem stems from trying to use the not-yet-fully-defined MyType type while defining it. You could do this with a union:

#include <iostream>

struct MyType {
    union {
        struct { long a, b, c; } data;
        char buffer[4096];
    };
};
static_assert(sizeof(MyType) == 4096, "MyType size should be exactly 4K");

int main() {
    MyType x;
    x.data.a = 42;
    std::cout << sizeof(x) << " " << x.data.a << "\n";
    return 0;
}

The output (on my system):

4096 42

Because it's a union, the type actually holds the a/b/c tuple and buffer area in an overlapped region of memory, big enough to hold the larger of the two. So, unless your long variable are really wide, that will be the 4K buffer area :-)

In any case, that size requirement is checked by the static_assert.

That may be less than ideal as buffer takes up the entire 4K. If instead you want to ensure that buffer is only the rest of the structure (after the long variables), you can use the following:

struct MyType {
    long a, b, c;
    char buffer[4096 - 3 * sizeof(long)];
};

and ensure that you use x.something rather than x.data.something when accessing the a, b, or c variables.

This solves your problem by using the size of three longs (these are fully defined) instead of the size of something not yet defined. It's still a good idea to keep the static_assert to ensure overall size is what you wanted.

like image 42
paxdiablo Avatar answered Oct 27 '22 01:10

paxdiablo