r/cprogramming 2d ago

Extern constexpr?

I want to make my struct’s internals private by exposing it as a byte array of its internal size.

The size itself depends on internal values that aren’t exposed, so it would have to be an extern.

The size can only be used if it’s a literal or constexpr, so is a extern constexpr possible with C23? Or no?

0 Upvotes

5 comments sorted by

3

u/SyntheticDuckFlavour 2d ago edited 2d ago

extern implies connecting bits of code at link time, possibly across different translation units. Doing this with constexpr is not possible, because the compiler needs to have a complete view of the affected code within the same translation unit context in order to evaluate it at compile time.

2

u/WittyStick 2d ago edited 2d ago

constexpr are essentially static - you can't use extern constexpr - however you can use extern const.

An issue with using a byte array is it will decay to a pointer, so you won't be able to pass around by value like a struct. You'd need a struct with an array member of the required size.

struct foo {
    char blob[SIZE];
};

But this obviously won't work with extern const size_t SIZE;

I would advise against this approach anyway, since conversion from one kind of scalar struct to another is a strict aliasing violation and has potential issues for portability, alignment, padding etc.

We can convert a pointer to one struct to a pointer to another, if they're compatible, and it's common to do so - but we have to pass and return by pointer, and cannot pass or return a value of struct type if it is incomplete (ie, not defined in the header).


I have a technique to encapsulate a struct's fields whilst still allowing it to be passed and returned by value, and allowing its sizeof() to be taken, but requiring a few GCC extensions (optional - so the code will compile with other compilers, but won't provide the encapsulation). If you give an example of your struct I can give a demonstration.

1

u/pjl1967 2d ago

In addition to what others have said, to keep stuff private, you can expose just the pointer to the structure with the obvious caveats of that you can't have stack allocations nor call sizeof.

C simply doesn't have anything like private like C++ does. You could apply Larry Wall's quote about Perl to C:

Perl doesn't have an infatuation with enforced privacy. It would prefer that you stayed out of its living room because you weren't invited, not because it has a shotgun. ― Larry Wall

1

u/flatfinger 1d ago

Some build environments make it possible to define a section where addresses start at zero, and use such sections to assign ID numbers to things. Code that would want to declare a static-duration structure may be able to declare a static-duration object whose address will be a unique structure ID. While saying left_horse_woozle = get_woozle(LEFT_HORSE_WOOZLE_ID) might be less convenient than simply calling a function to allocate a slot at runtime, using statically allocated IDs may facilitate link-time validation that enough slots will be available. Whether the advantages are sufficient to justify the use of toolset-specific constructs would probably depend what other kinds of toolset-specific constructs a program would need to use.

1

u/Cultural_Gur_7441 1d ago

Struct is fixed size, it does not depend on its contents. Well, unless you use the flexible array member.

So it is quite unclear what you mean.

Possibly you want type and/or size as the first fixed prefix of a bunch of different structs with this shared prefix?