Sujet : Re: C23 thoughts and opinions
De : bc (at) *nospam* freeuk.com (bart)
Groupes : comp.lang.cDate : 26. May 2024, 02:09:13
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <v2u23q$33ua5$1@dont-email.me>
References : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
User-Agent : Mozilla Thunderbird
On 25/05/2024 16:14, David Brown wrote:
On 25/05/2024 13:19, Thiago Adams wrote:
The justification for C was VLA. They should consider VLA not VLA if it has a constant expression. In other words, better break this than create a mess.
#define makes the job of constexpr.
>
#define is one way to make named items that can be used in constant expressions, yes. But if it can be done using #define or constexpr, I think constexpr is the neater choice. Opinions can vary - that's my opinion.
Before 'constexpr' (and it still is 'before' as implementations are rare), there were three disparate ways of emulating named constants in C:
#define A 100
enum {B = 200};
int const C = 300;
None of them fully do the job of the named constant feature I've used in my own languages (and which I also briefly had in my C compiler).
With 'constexpr' there are now 4 ways of doing it:
constexpr int D = 400;
Here are some characteristics of true named constants and how those methods fare:
#define enum const constexpr
Scope rules N Y Y Y
No & addr-of Y Y N N?
Any type Y? N Y Y Any int/float
Non-VLA bounds Y Y N Y?
Switch-case? Y Y N Y?
Reduce Y Y ? Y? 2+3 => 5
Can't Mod value Y Y N N? By any means
Not Context sens N Y Y Y Value may vary by context
Single reeval N Y Y Y Expr processed once
Lower case OK N? Y Y Y
Ideally a column would have all Ys. None of these manage that, but 'enum' comes nearest. However it has a problem: it wasn't designed for this task, which is just a useful by-product. So it looks odd.
With const/constexpr, even if the language can't stop attempts to change the value, sometimes those attempts are trapped (via read-only mem etc). That's not ideal either.
Regarding 'Not context sensitive', consider:
----------------------
#include <stdio.h>
enum {a = 100};
#define M (a+1)
enum {b = M};
int main(void) {
enum {a=777};
printf("b = %d\n", b);
printf("M = %d\n", M);
}
----------------------
The output is 101 and 778. The value of M is 101 when used to define `b`, and 778 later on.
'Single reevaluation' refers to the fact that the expansion of a #define macro will be repeated at each invocation side, so parsing, evaluation and reduction of the expression will be done multiple times. It's just inefficient.
It might also vary, not just because of the last point, but because there aren't enough parentheses or something so combines differently with surrounding context.