Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Format request]: C++ array #63

Open
jaskij opened this issue Aug 10, 2023 · 5 comments
Open

[Format request]: C++ array #63

jaskij opened this issue Aug 10, 2023 · 5 comments

Comments

@jaskij
Copy link

jaskij commented Aug 10, 2023

Call me crazy, but I program microcontrollers in C++.

To that end, while the C array is perfectly adequate, over the years the languages are diverging more and more. I propose adding a new output format, the C++ array.

The question is of specific output format, how it should be done.

My idea is to:

  • support C++11 and newer - C++03 can just use the C array
  • make a single output which is compatible with C++11, but utilizes newer features as appropriate

To that end, I believe the outline below to be appropriate. Although I would love for someone with a better grasp of the C++ standard to check if what I'm doing here with inline vs static is the right way.

#ifndef FOO_H
#define FOO_H

#ifndef SREC_CAT_QUALIFIER
    #ifdef __cpp_inline_variables
        #define SREC_CAT_QUALIFIER inline
    #else
        #define SREC_CAT_QUALIFIER static
    #endif
#endif

SREC_CAT_QUALIFIER constexpr std::array<uint8_t, LENGTH_HERE> foo = {
    // data goes here, the same as in the C array
};

SREC_CAT_QUALIFIER constexpr size_t foo_termination = 0x00;
SREC_CAT_QUALIFIER constexpr size_t foo_start       = 0x00;
SREC_CAT_QUALIFIER constexpr size_t foo_finish      = 0x00;

#endif // FOO_H

More on the inline keyword: cppreference.com notes:

Because the meaning of the keyword inline for functions came to mean "multiple definitions are permitted" rather than "inlining is preferred", that meaning was extended to variables.

If my understanding is correct, inline will result in more of a guarantee that the array will not be duplicated in the resulting program/library.

@jaskij
Copy link
Author

jaskij commented Aug 10, 2023

This came about because, while GCC will do what it always does, constexpr in theory gives more avenues for optimization than a simple const, especially if said const is extern.

@jaskij
Copy link
Author

jaskij commented Aug 10, 2023

To add: just now, the lack of constexpr has prevented me from using static_assert to make sure correct compile-time options were selected.

Edit: which was solved by including the generated .c file, but that always feels... bad.

@sierrafoxtrot
Copy link
Owner

Hi @jaskij, you certainly aren't alone in writing firmware in C++. I've been involved in doing just that on-and-off for the past 20+ years. This is a great idea!

Regarding C++ standards, I'd be keen to keep it to features from C++14 or earlier. This will give the best chance of aligning with a validated compiler for heavily regulated industries such as medical device development and safety systems. Implementing the actual format itself will be pretty straight forward (I've already done the boilerplate :-) )

As for the question around inline vs static vs [other option], I've reached out to a couple of friends and will give it some thought. Others who contribute to SRecord may also want to offer advice.

Meanwhile, regarding:

Edit: which was solved by including the generated .c file, but that always feels... bad.
Using the −INClude option will generate a .h intended to be included. If I've understood your dilemma, this may alleviate your conscience.

@jaskij
Copy link
Author

jaskij commented Aug 10, 2023

Regarding C++ standards, I'd be keen to keep it to features from C++14 or earlier.

From my knowledge, the only interesting point is inline, which was introduced in C++17. And which was #ifdefed in my proposal because of it. Hopefully I got the feature macro correctly.

Using the −INClude option will generate a .h intended to be included. If I've understood your dilemma, this may alleviate your conscience.

No, the C header doesn't work, because extern const cannot be used in a constexpr expression. And while I know that in practice static const is the same, I still prefer getting the constexpr. C++ is a bit too big to be able to accurately predict compiler behavior.

I work in a small company, with a lot of freedom, so I luckily have the option to use basically whatever ARM's latest release of GNU Toolchain supports (C++20, at the moment).

@jaskij
Copy link
Author

jaskij commented Mar 5, 2024

I got reminded of this issue recently, and just today learned about C23's #embed. Reading further ( https://thephd.dev/finally-embed-in-c23 ), it should probably make it into C++26.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants