Is enum a suitable way to implement a "local define?"


D

David Brown

I don't think I'm that comfortable with the idea.

If you did need something such as a set of pre-calculated tables, then
you might just use a script language to generate C code in an include file:

That can certainly be done - and it is a method I often use.
- You keep both languages simple

constexpr doesn't really make C++ any more complex - it just makes the
existing compile-time calculations more explicit.
- You don't have to re-run the calculations on every compilation (which
can include running the user's possibly slow, buggy code with the
likelihood of hanging the compiler is something is not right)

If the user's code is buggy, it is buggy no matter where it is executed.

And "make" will let you avoid re-generating your tables if they have not
changed.
- You use a tool (the script language) which can be more appropriate for
the job, especially if the output will be a string.

Sometimes that's true. But in cases where the pre-calculated data could
be generated within C++, keeping everything within the same language can
be a better choice.
- It easier to generate multiple values (ie. a table) rather than the
single-value constant definer we've been talking about


This is the same language where we won't even have official binary
constants until 2017?

Yes, though I don't quite see the connection. I don't claim that
constexpr makes C++ a "complete" or "perfect" language - it has plenty
of flaws. The same applies to C.

(gcc, and some other compilers for embedded targets, have had binary
constants for a good while now. It's an extension rather than a
standard feature.)
And the same one where you already /can/ define 'static const int
sizemax=1024', but it's not possible to use that to dimension an array?

C++ allows you to use static const ints as the dimension of an array.
I think maybe it ought to learn to walk before it can run!

I would like C to enhance its existing "const" (which was originally
copied from C++) to allow its use in array dimensions, just like in C++.
I cannot think of any reason why this is not in the C standards, and it
is a feature that would improve many C programs.

Copying "constexpr" from C++ into C would be less useful, but still have
its place - and it would be possible without "corrupting" C with too
much C++ style. Of course, in C it would be called "_Constexpr", but we
are used to that.
 
Ad

Advertisements

B

BartC

David Brown said:
On 07/04/14 14:27, BartC wrote:
.... And it is all declared "const" because
it will not change in the program, and should be in read-only flash
memory.

This is exactly why there needs to be a clear distinction between const used
for readonly data, and const to name magic numbers, which is what I was
talking about.

[David Brown]
Why? What possible justification do you have for introducing an
inconsistent and arbitrary extra syntax when there is a perfectly good,
clear and simple existing syntax?

Oh? I thought you wanted to move away from 'default int' in C, which is
exactly what you have with a constant such as 200 in source code. (BTW my
suggestion wasn't serious.)

My original suggestion for:

constant name = 123;

without the int, matches:

#define name 123

and:

enum {name=123};

and even:

123

used directly in source code, none of which need extra cues. But probably
the 'int' should be put in where it's not obvious:

constant int m = n*(n+1)/2;

Since n could be floating point, long int, etc.
 
D

David Brown

This is exactly why there needs to be a clear distinction between const
used
for readonly data, and const to name magic numbers, which is what I was
talking about.

No, there is /no/ need for such a distinction.

When the data involved is some sort of structure, or you have pointers,
it is going to end up (mostly) in readonly memory. But I want the
compiler to be able to take advantage of any compile-time-known values
to generate better code - I don't want to force the compiler to read
from flash (or rom, or whatever) if it doesn't have to.

And for data that is short and simple - such as "int" - I want the
compiler to use the shortest and fastest method of handling the data,
and I want it to be able to accept the number as a fixed
compile-time-known value for things like array sizes. I want the
compiler to find the best place to put the data depending on the
circumstances, and I want it to be able to put it in flash /and/ use it
directly, if that's the best choice.
[David Brown]
Why? What possible justification do you have for introducing an
inconsistent and arbitrary extra syntax when there is a perfectly good,
clear and simple existing syntax?

Oh? I thought you wanted to move away from 'default int' in C, which is
exactly what you have with a constant such as 200 in source code. (BTW my
suggestion wasn't serious.)

Yes, I want to move away from "default int" towards "explicit int" - not
towards "I think perhaps we'll use an "i" suffix here to say int.
Somewhere else we'll use "int", and perhaps somewhere else I'll pick a
different inconsistent convention".
My original suggestion for:

constant name = 123;

without the int, matches:

#define name 123

That is not part of C itself, it is part of the macro pre-processor
language which has no concept of "int" or any other type. So it is not
a "default int" - it is not even necessarily an int literal (you could
token-paste it to make a function name "foo123" if you want).

You can also use #define for floats, strings, and anything else you like.

But since we are doing away with the pre-processor defines, we should
not put too high an emphasis on them.
and:

enum {name=123};

Yes, but enum constants are completely and unchangeably integers. And
using enum in this way is an abuse of the enum keyword to get around the
limitations of const and static const values - so we should not copy
them either.
and even:

123

That's an integer literal.
used directly in source code, none of which need extra cues. But
probably the 'int' should be put in where it's not obvious:

constant int m = n*(n+1)/2;

Since n could be floating point, long int, etc.

The only existing concept that is worth copying here is the existing
"const", since that is what we are trying to improve upon. And that
requires an explicit type "const int name = 123".

And since "const" already does most of what we want, and in C++ it does
everything we want, then the C world would be better off by just
allowing "const" (or at least "static const") values to be used in the
same way as they can in C++.


One possible way to omit the type name, as suggested by another poster,
would be to make a new "constant" keyword that is of "auto" type, or at
least "auto" by default, based on C11 "auto". This is completely
different from "default int" - it would make the constant object of a
type that matches the initialiser. Thus "constant m = 1.23;" would make
"m" of type "const double" - unlike your default int idea in which
"constant m = 1.23;" would be an undiagnosed mistake in the code.
 
K

Keith Thompson

BartC said:
David Brown said:
On 07/04/14 00:20, BartC wrote:
Why should it be so easy to write a complex type definition as a single
statement?

Typedefs are fine when you want typedefs. But it's a failing to have to use
them to decipher a fairly ordinary type-spec; to declare:

'a as const pointer to array of pointer to char' I would need:

char *(* const a)[];

while to declare 'a as pointer to array of const pointer to char' I'd need:

char * const (*a)[];

Maybe /you/ can figure out which const means what, but I can't! (And don't
want to.) Look at the English description of each however, and it's
perfectly clear to which part each const pertains to.

I agree that C's declaration syntax is unnecessarily difficult. But
it's quite impossible to change it now, and there are tools like cdecl
and typedefs that can help you deal with the complexity.

You can learn to deal with it, or you can refrain from using C. (Or you
can complain about it here, but that's unlikely to be productive.)
So you want the type-spec on one line, and ideally you want it to be
obvious.

But another thing about const: which bit exactly of that last spec, could I
write to? I think (looking at the English!) you can modify the top pointer,
but not an array element, but *can* modify what the const array element
points to. All a bit meaningless really! More sensible would be just to have
a const qualifier at the top level.

I don't know what you mean by that last sentence. Sometimes you
*need* a modifiable pointer to read-only data, or a read-only
pointer to modifiable data (or modifiable/modifiable, or
read-only/read-only). A const qualifier at the top level can't
cover all those cases.

I have little doubt that one could design a syntax that would
express those cases more clearly than C's does.

And?

[...]
Why not? You don't have 'int' in a '#define constant, you don't have 'int'
in an enum constant, and you don't need 'int' in a const pseudo-constant!
This would make it just about the only place where it would be mandatory.

But the vast majority of named constants /will/ have int types.

There is exactly one "int type"; it's called "int". There are multiple
integer types. I can't tell which you're referring to.

As I said elsethread, I have no problem with a new construct where the
type is derived from the type of an expression, so that

const x = 1024;
const y = 1024U;
const z = (size_t)1024;

would make x, y, and z constants of type int, long, and size_t,
respectively.

Adding a new construct whose type specifically defaults to int would be
insane.

[...]
 
B

BartC

David Brown said:
On 07/04/14 15:43, BartC wrote:

No, there is /no/ need for such a distinction.
And since "const" already does most of what we want, and in C++ it does
everything we want, then the C world would be better off by just
allowing "const" (or at least "static const") values to be used in the
same way as they can in C++.

We'll have to disagree here. Take these four definitions:

constant int A = 1234; // proposed 'proper' constant

const int B = 1235;

int C = 1236;

int* D = &C;

They exhibit the following behaviour when used in a C expression:

Value Type ASM op

1233 1233 int load 1233
A 1234 int load A
B 1235 int load
C 1236 int load [C]
D pointer to 1236 int* load [D]
*D 1236 int load [[D]]

&1233 illegal --- ---
&A illegal --- ---
&B pointer to 1235 int* load B
&C pointer to 1236 int* load C
&D ptr to ptr to 1236 int** load [D]

While in ASM code, it's more like this:

1233 1233 int
A 1234 int
B Pointer to 1235 int*
C Pointer to 1236 int*
D Ptr to ptr to 1236 int**

Notice that B and C have identical behaviour, while A is quite different,
and in fact it is the same as the naked constant '1233'.

I want the ability to explicitly control whether a named entity has A/naked
constant-like behaviour, or B/C behaviour.

You're saying we should just forget about such distinctions, and leave it up
to the compiler. Even though C has #define, enum and naked constants that
are A-like in their behaviour, we aren't allowed to formalise those and have
everything in a proper package ('constant') with the scope and type
attributes that you might expect.
 
B

BartC

Keith Thompson said:
char *(* const a)[];
char * const (*a)[];

Maybe /you/ can figure out which const means what, but I can't! (And
don't
want to.) Look at the English description of each however, and it's
perfectly clear to which part each const pertains to.

I agree that C's declaration syntax is unnecessarily difficult. But
it's quite impossible to change it now, and there are tools like cdecl
and typedefs that can help you deal with the complexity.

You can learn to deal with it, or you can refrain from using C. (Or you
can complain about it here, but that's unlikely to be productive.)

(I once proposed a simpler left-to-right type-spec syntax here. I can't
remember details, but I think it was designed to co-exist with the existing
syntax. That would have meant some type-specs starting with "[" or "*",
which would have required a keyword to be inserted to avoid clashing with
other constructs.

Applied to my examples:

'a as const pointer to array of pointer to char' becomes:

const *[]*char a;

'a as pointer to array of const pointer to char' is:

*[]const* char a;

(The latter needing some dummy prefix if it is to co-exist. Maybe just
'newtype'!)

With simpler examples, new and old type-specs would identical. I don't know
if there are ambiguities where the specs look the same, but represent
different types according to interpretation. Use of permanent prefix would
fix that.)

Anyway, things can be done, it's not too late, but I suppose anyone who has
enough expertise to apply such changes will have got used to the old type
system.)
There is exactly one "int type"; it's called "int". There are multiple
integer types. I can't tell which you're referring to.

I'm referring to 'int'. In the same way that all the houses on my street
will have front doors. But only one each!
As I said elsethread, I have no problem with a new construct where the
type is derived from the type of an expression, so that

const x = 1024;
const y = 1024U;
const z = (size_t)1024;

would make x, y, and z constants of type int, long, and size_t,
respectively.

Adding a new construct whose type specifically defaults to int would be
insane.

No, as you have it, is exactly how I meant it. The default type is picked up
from the right-hand-side. If a type is provided, then the right-side is cast
to that type.
 
Ad

Advertisements

J

James Kuyper

And since "const" already does most of what we want, and in C++ it does
everything we want, then the C world would be better off by just
allowing "const" (or at least "static const") values to be used in the
same way as they can in C++.

We'll have to disagree here. Take these four definitions:

constant int A = 1234; // proposed 'proper' constant

const int B = 1235;

int C = 1236;

int* D = &C;

They exhibit the following behaviour when used in a C expression:

Value Type ASM op

1233 1233 int load 1233
A 1234 int load A
B 1235 int load


I've learned only three assembly languages, none of which used precisely
the same notation as you're using. How does "load A" differ from "load "?

The idea that there's a unique behavior associated with a C expression
ignores the fact that the meaning of C expressions depend upon the
context in which they are used. In particular, I'd expect quite
different behavior for the expression 'x' in a=x, b=&x, c=sizeof(x), and
d=_Alignof(x). In each of those four cases, I'd expect any decent
implementation of C to generate exactly the same code whether x is 1233
or B, except for b=&1233, which I would expect to trigger a diagnostic
message. It's not clear to me why different code would be generated for
A than would be generated by explicit use of 1234. Could you explain
that in more detail?

....
&B pointer to 1235 int* load B

No, it's a pointer to B, which contains a representation of 1235.
&C pointer to 1236 int* load C

That's a pointer to C, which is initialized with 1236, but need not have
that same value at the time the pointer is actually used.
While in ASM code, it's more like this:

1233 1233 int
A 1234 int
B Pointer to 1235 int*
C Pointer to 1236 int*
D Ptr to ptr to 1236 int**

That's a very peculiar ASM there - it looks a lot like C to me.
 
J

James Kuyper

On 04/07/2014 12:53 PM, James Kuyper wrote:
....
const int B = 1235; ....
... I'd expect any decent
implementation of C to generate exactly the same code whether x is 1233
or B, except for b=&1233,

In both places where I wrote 1233, it should have been 1235.
 
B

BartC

James Kuyper said:
On 04/07/2014 11:52 AM, BartC wrote:
constant int A = 1234; // proposed 'proper' constant

const int B = 1235;

int C = 1236;

int* D = &C;

They exhibit the following behaviour when used in a C expression:

Value Type ASM op

1233 1233 int load 1233
A 1234 int load A
B 1235 int load


I've learned only three assembly languages, none of which used precisely
the same notation as you're using. How does "load A" differ from "load
"?


load A is load immediate. (mov eax,A in Intel format I think) (0 memory
accesses)

load is load from memory (mov eax,) (1 memory access)

load [[C]] is a double memory access (eg mov esi,[C]; mov eax,[esi]). These
don't correspond to any real processors. The number of memory accesses is
more important.

I'll reply to other points later.
 
K

Keith Thompson

BartC said:
Keith Thompson said:
BartC said:
char *(* const a)[];
char * const (*a)[];

Maybe /you/ can figure out which const means what, but I can't! (And
don't want to.) Look at the English description of each however, and
it's perfectly clear to which part each const pertains to.

I agree that C's declaration syntax is unnecessarily difficult. But
it's quite impossible to change it now, and there are tools like cdecl
and typedefs that can help you deal with the complexity.

You can learn to deal with it, or you can refrain from using C. (Or you
can complain about it here, but that's unlikely to be productive.)

(I once proposed a simpler left-to-right type-spec syntax here. I can't
remember details, but I think it was designed to co-exist with the existing
syntax. That would have meant some type-specs starting with "[" or "*",
which would have required a keyword to be inserted to avoid clashing with
other constructs.

Applied to my examples:

'a as const pointer to array of pointer to char' becomes:

const *[]*char a;

'a as pointer to array of const pointer to char' is:

*[]const* char a;

(The latter needing some dummy prefix if it is to co-exist. Maybe just
'newtype'!)

With simpler examples, new and old type-specs would identical. I don't know
if there are ambiguities where the specs look the same, but represent
different types according to interpretation. Use of permanent prefix would
fix that.)

Anyway, things can be done, it's not too late, but I suppose anyone who has
enough expertise to apply such changes will have got used to the old type
system.)

I'm afraid it really is too late. You can undoubtedly invent a clearer
declaration syntax that could coexist with C's existing syntax. I can't
judge your proposed syntax without a complete specification (and, sorry,
but I probably wouldn't take the time even if you presented one), but
I don't think this:

*[]const* char a;

is sufficiently distinct from the existing syntax. If your proposal
were adopted in a new C standard, it would be difficult for a non-expert
to tell whether a declaration uses the old or new syntax.

And IMHO the only thing worse than C's current declaration syntax would
be C's current declaration syntax with another syntax grafted onto it.
Programmers would inevitably continue to use the existing syntax, and
*some* programmers would try to mix the two.

Most C programmers have already solved the problem for themselves: they
learn the existing syntax and try to avoid overly complex declarations.

I think the major obstacles to your idea are political rather than
technical.
I'm referring to 'int'. In the same way that all the houses on my street
will have front doors. But only one each!

Then you mean that the vast majority of named constants will have type
int.
No, as you have it, is exactly how I meant it. The default type is picked up
from the right-hand-side. If a type is provided, then the right-side is cast
to that type.

Then your proposal has nothing to do with "implicit int".

Given that, I think I like the idea. But (politics again) I think that
a clone of C++ semantics is more likely to make it into a future ISO C
standard.
 
G

glen herrmannsfeldt

(snip, I wrote)
What is it with language designers and the need to beat around
the bush with these things and not call things what they
actually are?

Well, that is a harder question. Java has static (but not final)
variables, which can be used in some of the same ways that static
variables are used in C. I believe also final, but not static,
though I have never tried. final variables much have an initializer
and can't be changed after that.

So, static final is used to define constants similar to the way
#define is often used in C. (Java has no preprocessor.) In addition,
the compiler guarantees not to compile code inside an if(false) block,
including if with a static final variable. (The code does have to pass
syntax check, unlike inside #ifdef/#endif.)

A class can also be final, which disallows subclassing.

-- glen
 
Ad

Advertisements

K

Kaz Kylheku

What is it with language designers and the need to beat around the bush with
these things and not call things what they actually are?

The curious, new vocabulary that appears in new computing projects is
the simple consequence of ignorance of prior art.

If, say, electrical engineering were like computing, the new crop of EE's would
be calling resistors "opposers".
 
P

partremmaps

Of course I could use malloc and all that but this isn't about that.



Often I do like the following:



int i

#define sizeMAX 1024

static char buffer[sizeMAX];

i=0;

while(i<sizeMAX)

{

putc(buffer);

}

... lots more code that reference buffer[] and sizeMAX ...

#undef sizeMAX





But this seems messy because I could forget the #undef and then that #define is left active for anything following in the code.



I tried const int sizeMAX=1024 but of course the declaration of buffer doesn't allow that as an array size specifier.



However, doing "enum { sizeMAX=1024 };" seems to work, but I can't tell from a quick word search in the standard whether it is supposed to always work.



Obviously enum was meant to map multiple words to a list of ints, and if the standard allows that list to be set up at run time then it may not work in some standard implementations.



Logically, "const int x=5" would be of the same functionality as "enum {x=5}" however GCC treats them differently, allowing the enum'ed x to be used as the array size specifier while not allowing the const int to be used as such.



Thanks,



Jesse




Thanks guys!


~Jesse
 
D

David Brown

David Brown said:
On 07/04/14 15:43, BartC wrote:

No, there is /no/ need for such a distinction.
And since "const" already does most of what we want, and in C++ it does
everything we want, then the C world would be better off by just
allowing "const" (or at least "static const") values to be used in the
same way as they can in C++.

We'll have to disagree here. Take these four definitions:

constant int A = 1234; // proposed 'proper' constant

const int B = 1235;

int C = 1236;

int* D = &C;

They exhibit the following behaviour when used in a C expression:

Value Type ASM op

1233 1233 int load 1233
A 1234 int load A
B 1235 int load
C 1236 int load [C]
D pointer to 1236 int* load [D]
*D 1236 int load [[D]]

&1233 illegal --- ---
&A illegal --- ---
&B pointer to 1235 int* load B
&C pointer to 1236 int* load C
&D ptr to ptr to 1236 int** load [D]

While in ASM code, it's more like this:

1233 1233 int
A 1234 int
B Pointer to 1235 int*
C Pointer to 1236 int*
D Ptr to ptr to 1236 int**

Notice that B and C have identical behaviour, while A is quite different,
and in fact it is the same as the naked constant '1233'.

I want the ability to explicitly control whether a named entity has A/naked
constant-like behaviour, or B/C behaviour.

You're saying we should just forget about such distinctions, and leave
it up
to the compiler. Even though C has #define, enum and naked constants that
are A-like in their behaviour, we aren't allowed to formalise those and
have
everything in a proper package ('constant') with the scope and type
attributes that you might expect.


Yes, we should forget about these distinctions. They are not true or
realistic anyway, so why try to pretend that they are?

Remember, a C compiler is /not/ a translator - it does not translate C
source code into assembly. It takes a /description/ or /specification/
of a task, written in the more-or-less carefully defined language C, and
generates object code that will have the same /visible/ effect as the
specified task.

Re-read that last paragraph, and think about it for a bit.

The compiler /will/ generate different types of code for different uses
of your objects here. If it knows the object in question cannot legally
be changed from 1234 (or whatever), then it can use that number directly
in the code - totally regardless of how it was defined. Conversely, if
it is more efficient to put a fixed constant in memory rather than
directly in code, then that is what the compiler will do. (This is a
common tactic on RISC processors, where loading a constant from memory
is often smaller and faster than using immediate addressing modes.)

I've said this all before, but until you understand that - until you
actually understand what C compilers /do/ - then we will be going round
in circles.

(Of course, there are some compilers that are so simple in construction
that they are basically translators, but that does not apply to "big"
compilers, and it is certainly not required by the C standards.)
 
D

David Brown

Given that, I think I like the idea. But (politics again) I think that
a clone of C++ semantics is more likely to make it into a future ISO C
standard.

A clone of the C++ semantics would let us write:

const auto x = 1234;
const auto y = 1024u;
const auto z = "Hello, world!";

int as[x];
int bs[y];


I would be happy with that. I would be so happy with it that I wouldn't
mind the extra "auto" that needs to be written.

I don't think there should be /too/ much resistance to adding this to C
- it is clearly technically feasible and useful, as it exists in current
C++ compilers. But the C standards world moves slowly!

(Of course, to enter the C world, "auto" would be called _Auto or
perhaps __auto_type, as in the gcc C extension.)
 
I

Ian Collins

David said:
Given that, I think I like the idea. But (politics again) I think that
a clone of C++ semantics is more likely to make it into a future ISO C
standard.

A clone of the C++ semantics would let us write:

const auto x = 1234;
const auto y = 1024u;
const auto z = "Hello, world!";

int as[x];
int bs[y];


I would be happy with that. I would be so happy with it that I wouldn't
mind the extra "auto" that needs to be written.

I don't think there should be /too/ much resistance to adding this to C
- it is clearly technically feasible and useful, as it exists in current
C++ compilers. But the C standards world moves slowly!

(Of course, to enter the C world, "auto" would be called _Auto or
perhaps __auto_type, as in the gcc C extension.)

Given auto is an existing keyword with a new meaning, it probably
wouldn't require the usual C ugliness
 
Ad

Advertisements

D

David Brown

David said:
Given that, I think I like the idea. But (politics again) I think that
a clone of C++ semantics is more likely to make it into a future ISO C
standard.

A clone of the C++ semantics would let us write:

const auto x = 1234;
const auto y = 1024u;
const auto z = "Hello, world!";

int as[x];
int bs[y];


I would be happy with that. I would be so happy with it that I wouldn't
mind the extra "auto" that needs to be written.

I don't think there should be /too/ much resistance to adding this to C
- it is clearly technically feasible and useful, as it exists in current
C++ compilers. But the C standards world moves slowly!

(Of course, to enter the C world, "auto" would be called _Auto or
perhaps __auto_type, as in the gcc C extension.)

Given auto is an existing keyword with a new meaning, it probably
wouldn't require the usual C ugliness

True, but it also means that there will be more battles about backwards
compatibility, and they can't be solved by making an "auto.h" header
containing "#define auto __auto_type". The C standards people are
always a bit hesitant (with good reason) to make a change that means
previously correct code is suddenly illegal.

I think, however, if one made "auto" ignored whenever a type was
specified, then old use of local variable definitions such as "auto int
i;" would then work as before.
 
S

Stephen Sprunk

BartC said:
Typedefs are fine when you want typedefs. But it's a failing to
have to use them to decipher a fairly ordinary type-spec; to
declare:

'a as const pointer to array of pointer to char' I would need:

char *(* const a)[];

while to declare 'a as pointer to array of const pointer to char'
I'd need:

char * const (*a)[];

Maybe /you/ can figure out which const means what, but I can't!
(And don't want to.) Look at the English description of each
however, and it's perfectly clear to which part each const pertains
to.

I agree that C's declaration syntax is unnecessarily difficult. But
it's quite impossible to change it now, and there are tools like
cdecl and typedefs that can help you deal with the complexity.

To change that is to change a core part of C: declaration mimics use.

The above examples are not that difficult, either, aside from the usual
need to read C declarations "inside out". The important part is to
remember that const binds to the left rather than to the right:

int const * a; // pointer to const int
int * const a; // const pointer to int
int const * const a; // const pointer to const int

The practice of writing "const int" rather than "int const", though,
makes this rule less obvious and IMHO should be avoided. That alone
probably explains why so many C programmers don't understand how to use
"const" properly, which leads to complaints of "const poisoning", etc.

S
 
K

Keith Thompson

David Brown said:
Given that, I think I like the idea. But (politics again) I think that
a clone of C++ semantics is more likely to make it into a future ISO C
standard.

A clone of the C++ semantics would let us write:

const auto x = 1234;
const auto y = 1024u;
const auto z = "Hello, world!";

int as[x];
int bs[y];


I would be happy with that. I would be so happy with it that I wouldn't
mind the extra "auto" that needs to be written.

I wasn't actually suggesting adding C++-style "auto", though I suppose I
wouldn't mind. What I was suggesting was that

const int x = 1234;
const unsigned y = 1024;

would make `x` and `y` constant expressions of type `int` and
`unsigned`, respectively. (x and y would still be addressible objects.)

Adding C++'s new (as of C++11) meaning for `auto` would be useful, but
less useful in C than it is in C++.
I don't think there should be /too/ much resistance to adding this to C
- it is clearly technically feasible and useful, as it exists in current
C++ compilers. But the C standards world moves slowly!

(Of course, to enter the C world, "auto" would be called _Auto or
perhaps __auto_type, as in the gcc C extension.)

`auto` is already a C keyword, a redundent storage class specifier that
specifies automatic storage duration. C++ dropped the old meaning when
adding the new one. I don't *think* there are any cases where the old
and new meanings conflict, but the meaning of

auto x = 1.5;

(which is valid in K&R C and I *think* is valid in C90, but illegal in
C99) would change.

I think C++'s treatment of const-qualified objects is more likely to
make it into a future C standard than its treatment of "auto".
 
Ad

Advertisements

S

Seungbeom Kim

To change that is to change a core part of C: declaration mimics use.

That rule ("declaration mimics use") by itself is not bad, I think,
but the problem lies in the fact that * is prefix, while [] and () are
postfix. Had C had a postfix pointer indirection operator, such as ^
in Pascal, both expressions and declarations would've been clearer.

int ap[2]^; // ap is an array of 2 pointers to int
// ap is an int^, ap^ is an int
int pa^[2]; // pa is a pointer to an array of 2 ints
// pa^ is an int[2], pa^ is an int

const char p^^; // p is a pointer to a pointer to const char
char p^ const^; // p is a pointer to a const pointer to char
char p const^^; // p is a const pointer to a pointer to char

And it->member would have been equivalent to it^.member,
which doesn't require a pair of parentheses. Moreover,
probably we wouldn't have needed the -> operator at all.

Too late for C, though. :(
The important part is to
remember that const binds to the left rather than to the right:

My rule has been rather to start from the identifier, read to the right
as long as you can, and then to the left; you need no special rule to
remember for const.
The practice of writing "const int" rather than "int const", though,
makes this rule less obvious and IMHO should be avoided.

Nevertheless, it wouldn't change the practice of writing "const int",
let alone the hugecode base that is already written with "const int".

I think it's just another thing that people need to learn and get
used to, just as (the bigger picture of) the declaration syntax.

(After all, there's nothing to the left of "const", so it has no other
option than to bind to the right. :))
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top