Thread overview
The "const"-war: resolution in the other direction?
May 26, 2004
Norbert Nemec
May 26, 2004
Kris
May 26, 2004
Norbert Nemec
May 26, 2004
Kris
May 26, 2004
Norbert Nemec
May 26, 2004
Hi there,

no, I do not plan to reopen the good old "const" war once again by defending the C++ position or trying to smuggle some of it into D. Just the contrary: maybe, it can be solved by going one step further:

Looking at the spec:
"The const attribute declares constants that can be evaluated at compile
time."

Why then should we speak of "storage" of constants at all? Primarily, a const is not "stored" at all. It is instead handled at compile time and can therefore be seen just like a literal. There is no way to take an address of a literal, therefore it should not be possible to take an address of a const either.

#############################
For primary type this already is, what happens:

------------------
const int x = 7;
int* y = &x;
------------------

will give you a compiler error "'7' is not an lvalue".
#############
For structs, the "const" seems to be ignored completely:

----------------
struct s {
    int x;
}

const s y = { x:7 };

int
main() {
    s* z = &y;
    z.x = 13;
    printf("%i\n",(*z).x);
    return 0;
}
----------------

will simply print "13"
#############
For strings:

----------------
const char[] str = "hallo";

int
main() {
    str[1] = 'e';
    printf(str);
    return 0;
}
----------------

gives a segfault at the assignment, probably because the data is stored in a
readonly data segment.
##############################################

This clearly is a mess. My suggestion would be to handle const structs and const arrays just like literals. Taking the address is not possible, instead, you would first have to copy the content to a local variable (just like for a literal). Passing const values as inout/out parameters is not possible.

For in parameters, it would first have to be cleared up whether "in" means call-by-value or call-by-reference. In the first case, there is no problem. In the second case, the compiler should make sure, that the argument really is not written to. Effectively, this would mean, that "in" arguments can only be handled like constants: assignment is not possible, taking the address is not possible, and they can only be used as "in" parameters.

Unlike C/C++, where arguments automatically turn into local variables, this would not be the case for "in" arguments.

Ciao,
Nobbi

May 26, 2004
Part of the problem here is that 'const' is overloaded:

1) a compile-time constant, such as your example below

2) a function/method argument that disallows write-access as part of DbC

3) read-only data, which can be placed in an alternate physical medium such as ROM

The first two get all the attention, but I'd like to remind folks about the value of #3 ... arguably the dominant factor when it comes to the world's most prevalent CPU: the humble microcontroller. This is why 'const' is oft discussed in terms of "storage class".

I'm tempted to argue that only #3 has the right to be called 'const', since #1 is handled by folding, or enum, or whatever, and #2 should be handled by the 'in' keyword ...

- Kris


"Norbert Nemec" <Norbert.Nemec@gmx.de> wrote in message news:c91fvi$ru8$1@digitaldaemon.com...
> Hi there,
>
> no, I do not plan to reopen the good old "const" war once again by
defending
> the C++ position or trying to smuggle some of it into D. Just the
contrary:
> maybe, it can be solved by going one step further:
>
> Looking at the spec:
> "The const attribute declares constants that can be evaluated at compile
> time."
>
> Why then should we speak of "storage" of constants at all? Primarily, a const is not "stored" at all. It is instead handled at compile time and
can
> therefore be seen just like a literal. There is no way to take an address of a literal, therefore it should not be possible to take an address of a const either.
>
> #############################
> For primary type this already is, what happens:
>
> ------------------
> const int x = 7;
> int* y = &x;
> ------------------
>
> will give you a compiler error "'7' is not an lvalue".
> #############
> For structs, the "const" seems to be ignored completely:
>
> ----------------
> struct s {
>     int x;
> }
>
> const s y = { x:7 };
>
> int
> main() {
>     s* z = &y;
>     z.x = 13;
>     printf("%i\n",(*z).x);
>     return 0;
> }
> ----------------
>
> will simply print "13"
> #############
> For strings:
>
> ----------------
> const char[] str = "hallo";
>
> int
> main() {
>     str[1] = 'e';
>     printf(str);
>     return 0;
> }
> ----------------
>
> gives a segfault at the assignment, probably because the data is stored in
a
> readonly data segment. ##############################################
>
> This clearly is a mess. My suggestion would be to handle const structs and const arrays just like literals. Taking the address is not possible, instead, you would first have to copy the content to a local variable
(just
> like for a literal). Passing const values as inout/out parameters is not possible.
>
> For in parameters, it would first have to be cleared up whether "in" means call-by-value or call-by-reference. In the first case, there is no
problem.
> In the second case, the compiler should make sure, that the argument
really
> is not written to. Effectively, this would mean, that "in" arguments can only be handled like constants: assignment is not possible, taking the address is not possible, and they can only be used as "in" parameters.
>
> Unlike C/C++, where arguments automatically turn into local variables,
this
> would not be the case for "in" arguments.
>
> Ciao,
> Nobbi
>


May 26, 2004
Kris wrote:

> Part of the problem here is that 'const' is overloaded:
> 
> 1) a compile-time constant, such as your example below
> 
> 2) a function/method argument that disallows write-access as part of DbC
> 
> 3) read-only data, which can be placed in an alternate physical medium such as ROM
> 
> The first two get all the attention, but I'd like to remind folks about the value of #3 ... arguably the dominant factor when it comes to the world's most prevalent CPU: the humble microcontroller. This is why 'const' is oft discussed in terms of "storage class".

Very true.

> I'm tempted to argue that only #3 has the right to be called 'const', since #1 is handled by folding, or enum, or whatever, and #2 should be handled by the 'in' keyword ...

I have not much experience in microcontrollers, but where would be the difference to normal programs that may also have read-only data segments? Is there need to directly handle references to read-only memory? Call by reference would not be a problem, since that would be handled by the 'in' modifier. But would you need "pointer to const" as an explicit data type?

May 26, 2004
"Norbert Nemec"  wrote
> I have not much experience in microcontrollers, but where would be the difference to normal programs that may also have read-only data segments? Is there need to directly handle references to read-only memory? Call by reference would not be a problem, since that would be handled by the 'in' modifier. But would you need "pointer to const" as an explicit data type?

My experience vis-a-vis MCUs pertains purely to the use of const as a RO segment identifier, so I'd be tempted to say no. I wonder if some Harvard-style architectures might benefit from what you suggest? Too many options ...

(BTW, using 'const' to isolate entire fonts/resources into ROM on a device with 2K RAM is a blissful convenience).

- Kris


May 26, 2004
Kris wrote:

> "Norbert Nemec"  wrote
>> I have not much experience in microcontrollers, but where would be the difference to normal programs that may also have read-only data segments? Is there need to directly handle references to read-only memory? Call by reference would not be a problem, since that would be handled by the 'in' modifier. But would you need "pointer to const" as an explicit data type?
> 
> My experience vis-a-vis MCUs pertains purely to the use of const as a RO segment identifier, so I'd be tempted to say no. I wonder if some Harvard-style architectures might benefit from what you suggest? Too many options ...
> 
> (BTW, using 'const' to isolate entire fonts/resources into ROM on a device with 2K RAM is a blissful convenience).

I think that concept of 'const' goes along very well with the concept of 'const' for values that can be calculated at compile time. Just leave it to the compiler to decide whether some data needs some physical (RO-)memory, or whether it can just be used like any literal. If you have a const struct, it does not automatically need to be allocated in ROM. And if the compiler decides that there is need to have it as data in memory explicitely, it can simply allocate it in ROM.