On 10/06/2025 18:43, Christopher Bazley wrote:
Hi David,

On 10/06/2025 14:19, David Brown wrote:
On 10/06/2025 10:43, Jakub Jelinek wrote:
On Tue, Jun 10, 2025 at 09:52:42AM +0200, David Brown via Gcc wrote:
So while correcting the mistakes of the past is either very slow or
impossible, we can avoid them in the future.  Consistent parameter order
makes code clearer and neater, and should be encouraged.


For context here, I am a C and gcc user, not a developer of either the compiler or libraries.  That means I have no direct influence on any of this, and I do not have nearly as wide an experience with different C developers and different C code as many of the others here - my experience is focused on small-systems embedded development.  So that means my thoughts or opinions here might be very skewed, and not very applicable to the wider world of C.  I give my thoughts here in the hope that they might be useful, but I am fully aware that I can be missing some of the big picture.

If the clauses are properly documented, enforcing some order is just a
hassle to users who will need to remember the ordering (which won't be
obvious).

I disagree.  Obviously I agree that proper documentation is good. But I think enforced order can be very useful too.  This is particularly important for new or rarely-used features of a language.  Having an enforced order can actually mean one /less/ thing for people to learn - not /more/ for them to remember.  It means when they look at examples or other people's code, which is one of the main ways people learn about new features (very few C programmers actually read the standards or reference resources like en.cppreference.com), the existing code is more consistent. No one has to wonder why people have used different orderings, or what difference it makes.

There is often a good argument to be made for consistency. For example, in a project that commonly uses the directive

#if defined(X) && defined (Y)

it could be annoying or confusing for one instance out of one hundred to instead read

#if defined(Y) && defined(X)

However, nobody would seriously advocate that the order of operands to && should be enforced by the language. Instead, this is treated a matter for coding standards, taste, and common sense. Some programmers care about such things; others don't. It can also vary from project to project. Having the compiler attempt to enforce someone's idea of "good" style is a blunt instrument.

Yes, there are balances and trade-offs. Different projects and different types of code have wildly different requirements.

I am not sure if the order of parameters in #embed should be fixed. I am sure it would have advantages, and sure it would have disadvantages, and I am not sure about where the best balance lies in this case. I am, however, sure that "C is liberal about ordering in certain other situations" is not a good argument.

I know that if /I/ use #embed, I will be consistent about the ordering. But that does not mean other people should be required to use the same ordering. That decision should not be made based on my preferences and arguably obsessive coding style - it should be based on a balance of real pros and real cons.


The #embed parameters are really similar to OpenMP/OpenACC clauses
and those haven't enforced any particular ordering for 25+ years (the only exception are unnamed clauses that on certain directives must appear first
followed by other clauses).

I don't think that is a good argument unless you have reason to say that the flexibility of ordering was a good thing in OpenMP clauses, and can show that code is clearer, safer, more efficient, easier to maintain, or otherwise "better" as a result of people being able to use different orders of parameters in OpenMP clauses.  If you have reason to believe that flexible ordering lets people write better code OpenMP code, and that the same effect will let people write better #embed code, then that's fair enough - and good reason to copy that practice.  But the precedence alone is not a strong reason.  (It's maybe strong enough if you think it really doesn't matter whether there is an order or not to the #embed parameters.)

Assuming that enforcing an order is more complex than not enforcing it (which seems likely, especially when taking into account the fact that associated configuration might be needed to opt in or out), I think that simplicity is a good enough reason in itself not to enforce the order.


There is a strong tradition in C that complexity of implementation is not considered a major factor in language design decisions. And I do not believe that enforcing an order here would be significantly more complex to implement. With all due respect (and thanks!) to the fantastic people who write and maintain gcc, I don't care if a change here is a little harder to implement if it is a little clearer for people /using/ the feature.

If you think #embed would be simpler to /use/ without enforcing an order, then that would be a good reason. But this whole discussion is the result of people wondering if "offset(1) limit(3)" means the same as "limit(3) offset(1)", suggesting to me that freedom of order is /not/ simpler in use.

The limit/offset clauses are handled at a different time during
preprocessing than if_empty/prefix/suffix, the former to find out what part of data if any will be read from the file (if it exists), the latter when
the directive is being replaced by new tokens.

Having the clauses ordered that way then makes more sense to me.

Making the order relevant would also make the whole thing more flexible for future enhancements - in the future, someone might be interested in adding filtering or transformation parameters.  (In C++, that could always be done with constexpr functions and ranges, but C does not have these.)  But maybe that idea is going too far beyond the scope of #embed.

If anyone ever wants such a thing, I hope they come up with less subtle syntax.

I can't say that /I/ would want it (I use Python scripts to generate .c and .h files as needed, but will probably move to #embed for simple cases). But I could imagine things like endian swapping, or using the data in different unit sizes being relatively simple to specify and having wide potential use.


To be honest, I'm still not entirely comfortable with the fact that these two commands have different effects:

cat a.txt >b.txt 2>&1
cat a.txt 2>&1 >b.txt


I don't find it so surprising that these are different, but I was a little surprised at which one gave which results. I suppose I don't do enough complex shell redirections for my intuition to match bash reality.


Reply via email to