Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #163193 > unrolled thread
| Started by | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| First post | 2021-10-28 12:50 -0300 |
| Last post | 2021-10-29 17:04 -0300 |
| Articles | 20 on this page of 32 — 10 participants |
Back to article view | Back to comp.lang.c
on the order of the const-keyword Meredith Montgomery <mmontgomery@levado.to> - 2021-10-28 12:50 -0300
Re: on the order of the const-keyword Bart <bc@freeuk.com> - 2021-10-28 17:25 +0100
Re: on the order of the const-keyword "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> - 2021-10-28 10:10 -0700
Re: on the order of the const-keyword Guillaume <message@bottle.org> - 2021-10-28 20:40 +0200
Re: on the order of the const-keyword Meredith Montgomery <mmontgomery@levado.to> - 2021-10-29 00:07 -0300
Re: on the order of the const-keyword James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-10-29 00:48 -0400
Re: on the order of the const-keyword Thiago Adams <thiago.adams@gmail.com> - 2021-10-28 12:56 -0700
Re: on the order of the const-keyword Thiago Adams <thiago.adams@gmail.com> - 2021-10-28 13:18 -0700
Re: on the order of the const-keyword Bart <bc@freeuk.com> - 2021-10-28 21:35 +0100
Re: on the order of the const-keyword Thiago Adams <thiago.adams@gmail.com> - 2021-10-28 13:57 -0700
Re: on the order of the const-keyword Thiago Adams <thiago.adams@gmail.com> - 2021-10-28 14:07 -0700
Re: on the order of the const-keyword Bart <bc@freeuk.com> - 2021-10-28 22:54 +0100
Re: on the order of the const-keyword Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-10-28 15:37 -0700
Re: on the order of the const-keyword Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-10-29 00:02 +0100
Re: on the order of the const-keyword Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-10-28 22:10 +0100
Re: on the order of the const-keyword Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-10-28 15:13 -0700
Re: on the order of the const-keyword Meredith Montgomery <mmontgomery@levado.to> - 2021-10-29 00:40 -0300
Re: on the order of the const-keyword Meredith Montgomery <mmontgomery@levado.to> - 2021-10-28 23:48 -0300
Re: on the order of the const-keyword James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-10-28 13:04 -0400
Re: on the order of the const-keyword Meredith Montgomery <mmontgomery@levado.to> - 2021-10-29 00:34 -0300
Re: on the order of the const-keyword David Brown <david.brown@hesbynett.no> - 2021-10-29 10:03 +0200
Re: on the order of the const-keyword Bart <bc@freeuk.com> - 2021-10-29 11:30 +0100
Re: on the order of the const-keyword David Brown <david.brown@hesbynett.no> - 2021-10-29 16:31 +0200
Re: on the order of the const-keyword Bart <bc@freeuk.com> - 2021-10-29 16:45 +0100
Re: on the order of the const-keyword David Brown <david.brown@hesbynett.no> - 2021-10-29 18:30 +0200
Re: on the order of the const-keyword Manfred <noname@add.invalid> - 2021-10-30 00:32 +0200
Re: on the order of the const-keyword Meredith Montgomery <mmontgomery@levado.to> - 2021-10-29 20:03 -0300
Re: on the order of the const-keyword Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-10-30 01:10 +0100
Re: on the order of the const-keyword Bart <bc@freeuk.com> - 2021-10-29 23:51 +0100
Re: on the order of the const-keyword Meredith Montgomery <mmontgomery@levado.to> - 2021-10-29 12:22 -0300
Re: on the order of the const-keyword David Brown <david.brown@hesbynett.no> - 2021-10-29 18:34 +0200
Re: on the order of the const-keyword Meredith Montgomery <mmontgomery@levado.to> - 2021-10-29 17:04 -0300
Page 1 of 2 [1] 2 Next page →
| From | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| Date | 2021-10-28 12:50 -0300 |
| Subject | on the order of the const-keyword |
| Message-ID | <86mtmtm9m1.fsf@levado.to> |
These seem legal declarations in C:
const char msg[9] = "warming:";
char const msg[9] = "warming:";
What's the difference between them?
(*) Note to self
When I tried changing that array, the compiler did not let me to ---
with either declaration. (So it appears there is no *effective*
difference.)
%cat msg.c
#include <stdio.h>
int main(void) {
char const msg[9] = "warming:";
msg[0]= 'f';
printf("%s\n", msg);
}
%make msg
gcc msg.c -o msg
msg.c: In function 'main':
msg.c:6:9: error: assignment of read-only location 'msg[0]'
6 | msg[0]= 'f';
| ^
make: *** [<builtin>: msg] Error 1
%
[toc] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-10-28 17:25 +0100 |
| Message-ID | <sleiul$8m0$1@dont-email.me> |
| In reply to | #163193 |
On 28/10/2021 16:50, Meredith Montgomery wrote:
> These seem legal declarations in C:
>
> const char msg[9] = "warming:";
> char const msg[9] = "warming:";
>
> What's the difference between them?
There is no difference. You can even write:
const char const msg[9];
'const' (as well as short, int, long, float, double, even static and
typedef) can occur anywhere, in any combination, in the declaration of a
base type (what goes on the left before the first variable).
'const' can also be repeated any number of times:
char const const const const const const msg[9]
if you want to be certain that msg is constant!
However when applied to a pointer, then it must go after *.
[toc] | [prev] | [next] | [standalone]
| From | "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-10-28 10:10 -0700 |
| Message-ID | <2a5589c2-89ac-4d77-a91d-508c00f75e43n@googlegroups.com> |
| In reply to | #163196 |
On Thursday, October 28, 2021 at 12:26:09 PM UTC-4, Bart wrote: ... > 'const' (as well as short, int, long, float, double, even static and > typedef) can occur anywhere, in any combination, in the declaration of a > base type (what goes on the left before the first variable). ... > However when applied to a pointer, then it must go after *. const char * p char * const q; char const * const r; are all permitted. p is a pointer to const char. q is a const pointer to char. r is a const pointer to const char.
[toc] | [prev] | [next] | [standalone]
| From | Guillaume <message@bottle.org> |
|---|---|
| Date | 2021-10-28 20:40 +0200 |
| Message-ID | <sleqrn$d2j$1@gioia.aioe.org> |
| In reply to | #163198 |
Le 28/10/2021 à 19:10, james...@alumni.caltech.edu a écrit : > On Thursday, October 28, 2021 at 12:26:09 PM UTC-4, Bart wrote: > ... >> 'const' (as well as short, int, long, float, double, even static and >> typedef) can occur anywhere, in any combination, in the declaration of a >> base type (what goes on the left before the first variable). > ... >> However when applied to a pointer, then it must go after *. > > const char * p > char * const q; > char const * const r; > > are all permitted. p is a pointer to const char. q is a const pointer to char. r is a const pointer to const char. Yes indeed! With pointer declarations, 'const' has a different meaning depending on where it is located relative to '*', as you showed.
[toc] | [prev] | [next] | [standalone]
| From | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| Date | 2021-10-29 00:07 -0300 |
| Message-ID | <86y26cle9j.fsf@levado.to> |
| In reply to | #163198 |
"james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> writes:
> On Thursday, October 28, 2021 at 12:26:09 PM UTC-4, Bart wrote:
> ...
>> 'const' (as well as short, int, long, float, double, even static and
>> typedef) can occur anywhere, in any combination, in the declaration of a
>> base type (what goes on the left before the first variable).
> ...
>> However when applied to a pointer, then it must go after *.
>
> const char * p
> char * const q;
> char const * const r;
>
> are all permitted. p is a pointer to const char. q is a const pointer
> to char. r is a const pointer to const char.
So the order does make a difference here. I mean
char const * r1
is not the same
char const * const r2
because r2 cannot point somewhere else but r1 can.
Thank you.
(*) So, I wrote this to check
#include <stdio.h>
int main()
{
const char c1 = 'x';
const char c2 = 'y';
const char* r1 = &c1;
const char* const r2 = &c1;
printf("r1 = %c, r2 = %c\n", *r1, *r2);
r1 = &c2;
/* r2 = &c2; */ /* cant do this */
printf("r1 = %c, r2 = %c\n", *r1, *r2);
return 0;
}
(*) What have I learned here as well?
When we declare something to be const we also have to define it in the
statement. IOW, I cannot separate declaration and definition of a const
thing. This makes sense --- if I can assign a const-thing, how would
the compiler keep me from changing it? (But it wasn't clear to me 'til
now.)
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-10-29 00:48 -0400 |
| Message-ID | <slfuf4$p46$1@dont-email.me> |
| In reply to | #163218 |
On 10/28/21 11:07 PM, Meredith Montgomery wrote: > "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> writes: > >> On Thursday, October 28, 2021 at 12:26:09 PM UTC-4, Bart wrote: >> ... >>> 'const' (as well as short, int, long, float, double, even static and >>> typedef) can occur anywhere, in any combination, in the declaration of a >>> base type (what goes on the left before the first variable). >> ... >>> However when applied to a pointer, then it must go after *. >> >> const char * p >> char * const q; >> char const * const r; >> >> are all permitted. p is a pointer to const char. q is a const pointer >> to char. r is a const pointer to const char. > > So the order does make a difference here. I mean > > char const * r1 > > is not the same > > char const * const r2 > > because r2 cannot point somewhere else but r1 can. > > Thank you. The top-level grammar for such a declaration is declaration-specifiers init-declarator-list opt ; "char const" are the declaration specifiers, while the init-declarator-list consists of a single declarator with no initializer, which is "* const r2". "r2" is the identifier being declared, and after any "*" in a declarator there may be additional type qualifiers that are not part of the initial list of declaration specifiers. Unlike the order of the declaration specifiers, the order of the type qualifiers relative to the "*"s is VERY important.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2021-10-28 12:56 -0700 |
| Message-ID | <a25df1f0-687b-4489-8f2f-6daa35593040n@googlegroups.com> |
| In reply to | #163196 |
On Thursday, October 28, 2021 at 1:26:09 PM UTC-3, Bart wrote: > On 28/10/2021 16:50, Meredith Montgomery wrote: > > These seem legal declarations in C: > > > > const char msg[9] = "warming:"; > > char const msg[9] = "warming:"; > > > > What's the difference between them? > There is no difference. You can even write: > > const char const msg[9]; > > > 'const' (as well as short, int, long, float, double, even static and > typedef) can occur anywhere, in any combination, in the declaration of a > base type (what goes on the left before the first variable). > > 'const' can also be repeated any number of times: > > char const const const const const const msg[9] We can also add as many parentheses as we like. char const const const const const const ((((((msg))))))[9]; :D
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2021-10-28 13:18 -0700 |
| Message-ID | <994066a9-5940-4d1c-8df4-517905174930n@googlegroups.com> |
| In reply to | #163201 |
On Thursday, October 28, 2021 at 4:56:18 PM UTC-3, Thiago Adams wrote: ... > > 'const' (as well as short, int, long, float, double, even static and > > typedef) can occur anywhere, in any combination, in the declaration of a > > base type (what goes on the left before the first variable). I also have a new definition for typedef considering how it works. We use to say typedef is a alias for a type name. But here , typedef int Int; typedef unsigned Int T; //error Int does not work as a alias for int. So my definition is: when we put typedef in a declaration we declare a variable that has no storage. When we use this variable is the same of using typeof(variable) but we write just the variable name. Int x; So typedef is more like "use the same type of that variable here". considering this.... I was also considering to use typedef to define constants typedef double pi = 3.14; or valuedef double pi = 3.14; pi is a non-storage variable, but instead of copying its type we copy its initialization value. double x = pi;
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-10-28 21:35 +0100 |
| Message-ID | <slf1ic$qcv$1@dont-email.me> |
| In reply to | #163202 |
On 28/10/2021 21:18, Thiago Adams wrote:
> On Thursday, October 28, 2021 at 4:56:18 PM UTC-3, Thiago Adams wrote:
> ...
>>> 'const' (as well as short, int, long, float, double, even static and
>>> typedef) can occur anywhere, in any combination, in the declaration of a
>>> base type (what goes on the left before the first variable).
>
> I also have a new definition for typedef considering how it works.
>
> We use to say typedef is a alias for a type name.
>
> But here ,
>
> typedef int Int;
> typedef unsigned Int T; //error
>
> Int does not work as a alias for int.
I think this is reasonable behavour. To make it work as you want, as an
alias for the 'int' /token/, then it can be done as:
#define Int int
For a composite type like 'int long long', it must be a valid
combination of those tokens. The alias 'T' may be defined internally as
a complete type 'signed long long int'.
You can't then modify it as 'unsigned signed long long int' even if you
could sort out the parsing.
For example, you can't do 'unsigned int32_t'.
>
> So my definition is:
> when we put typedef in a declaration we declare a variable that has no
> storage.
I can never remember how typedef works, and have to pretend that it is
'static', and I'm declaring a normal variable name.
> When we use this variable is the same of using typeof(variable) but
> we write just the variable name.
> Int x;
> So typedef is more like "use the same type of that variable here".
>
> considering this.... I was also considering to use typedef to define constants
>
> typedef double pi = 3.14;
> or
> valuedef double pi = 3.14;
>
> pi is a non-storage variable, but instead of copying its type
> we copy its initialization value.
I tried something like that. I couldn't use 'const' as that was taken; I
used 'constant':
constant int a = 1233;
constant double b = a/10.0;
printf("%d\n", a);
printf("%f\n", b);
This could be tweaked to infer the type from the expression.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2021-10-28 13:57 -0700 |
| Message-ID | <7697a67c-fc7e-4b7c-b53f-38076b50cde2n@googlegroups.com> |
| In reply to | #163203 |
On Thursday, October 28, 2021 at 5:35:36 PM UTC-3, Bart wrote:
> On 28/10/2021 21:18, Thiago Adams wrote:
> > On Thursday, October 28, 2021 at 4:56:18 PM UTC-3, Thiago Adams wrote:
> > ...
> >>> 'const' (as well as short, int, long, float, double, even static and
> >>> typedef) can occur anywhere, in any combination, in the declaration of a
> >>> base type (what goes on the left before the first variable).
> >
> > I also have a new definition for typedef considering how it works.
> >
> > We use to say typedef is a alias for a type name.
> >
> > But here ,
> >
> > typedef int Int;
> > typedef unsigned Int T; //error
> >
> > Int does not work as a alias for int.
> I think this is reasonable behavour. To make it work as you want, as an
> alias for the 'int' /token/, then it can be done as:
>
> #define Int int
>
> For a composite type like 'int long long', it must be a valid
> combination of those tokens. The alias 'T' may be defined internally as
> a complete type 'signed long long int'.
>
> You can't then modify it as 'unsigned signed long long int' even if you
> could sort out the parsing.
>
> For example, you can't do 'unsigned int32_t'.
> >
> > So my definition is:
> > when we put typedef in a declaration we declare a variable that has no
> > storage.
> I can never remember how typedef works, and have to pretend that it is
> 'static', and I'm declaring a normal variable name.
> > When we use this variable is the same of using typeof(variable) but
> > we write just the variable name.
> > Int x;
> > So typedef is more like "use the same type of that variable here".
> >
> > considering this.... I was also considering to use typedef to define constants
> >
> > typedef double pi = 3.14;
> > or
> > valuedef double pi = 3.14;
> >
> > pi is a non-storage variable, but instead of copying its type
> > we copy its initialization value.
> I tried something like that. I couldn't use 'const' as that was taken; I
> used 'constant':
>
> constant int a = 1233;
> constant double b = a/10.0;
>
> printf("%d\n", a);
> printf("%f\n", b);
>
> This could be tweaked to infer the type from the expression.
and because there is no storage we cannot take &a or &b.
BUT I think there is a hidden variable instantiated (just like compound literals)
For instance this is C99.
struct X { int i; };
void F(struct X* x) {}
struct X c = { . i = 1 };
int main() {
F(& (struct X) {.i = 1}); //variable is created
F(&c);
}
in this C99 sample c HAS storage. it exists.
Now lets consider we have this "constant".
struct X { int i; };
void F(struct X* x) {}
constant struct X c = { . i = 1 }; //no storage
int main() {
F(& (struct X) {.i = 1});
F(&c); //what happens here?
}
When we call F(&c) some variable should be instantiated.?
At the end it could work as enumerators work today
enum { A = 1 };
void F(int* i) {}
void F2(int i) {}
int main() {
F(&A); //error: lvalue required as unary '&' operand
F2(A); //OK
}
sometimes a local variable would be created, except for int double etc..
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2021-10-28 14:07 -0700 |
| Message-ID | <aadf2b60-6c41-434a-8c19-8fc2a60bff15n@googlegroups.com> |
| In reply to | #163204 |
On Thursday, October 28, 2021 at 5:57:38 PM UTC-3, Thiago Adams wrote:
> On Thursday, October 28, 2021 at 5:35:36 PM UTC-3, Bart wrote:
> > On 28/10/2021 21:18, Thiago Adams wrote:
> > > On Thursday, October 28, 2021 at 4:56:18 PM UTC-3, Thiago Adams wrote:
> > > ...
> > >>> 'const' (as well as short, int, long, float, double, even static and
> > >>> typedef) can occur anywhere, in any combination, in the declaration of a
> > >>> base type (what goes on the left before the first variable).
> > >
> > > I also have a new definition for typedef considering how it works.
> > >
> > > We use to say typedef is a alias for a type name.
> > >
> > > But here ,
> > >
> > > typedef int Int;
> > > typedef unsigned Int T; //error
> > >
> > > Int does not work as a alias for int.
> > I think this is reasonable behavour. To make it work as you want, as an
> > alias for the 'int' /token/, then it can be done as:
> >
> > #define Int int
> >
> > For a composite type like 'int long long', it must be a valid
> > combination of those tokens. The alias 'T' may be defined internally as
> > a complete type 'signed long long int'.
> >
> > You can't then modify it as 'unsigned signed long long int' even if you
> > could sort out the parsing.
> >
> > For example, you can't do 'unsigned int32_t'.
> > >
> > > So my definition is:
> > > when we put typedef in a declaration we declare a variable that has no
> > > storage.
> > I can never remember how typedef works, and have to pretend that it is
> > 'static', and I'm declaring a normal variable name.
> > > When we use this variable is the same of using typeof(variable) but
> > > we write just the variable name.
> > > Int x;
> > > So typedef is more like "use the same type of that variable here".
> > >
> > > considering this.... I was also considering to use typedef to define constants
> > >
> > > typedef double pi = 3.14;
> > > or
> > > valuedef double pi = 3.14;
> > >
> > > pi is a non-storage variable, but instead of copying its type
> > > we copy its initialization value.
> > I tried something like that. I couldn't use 'const' as that was taken; I
> > used 'constant':
> >
> > constant int a = 1233;
> > constant double b = a/10.0;
> >
> > printf("%d\n", a);
> > printf("%f\n", b);
> >
> > This could be tweaked to infer the type from the expression.
> and because there is no storage we cannot take &a or &b.
> BUT I think there is a hidden variable instantiated (just like compound literals)
>
> For instance this is C99.
>
> struct X { int i; };
> void F(struct X* x) {}
> struct X c = { . i = 1 };
> int main() {
> F(& (struct X) {.i = 1}); //variable is created
> F(&c);
> }
>
> in this C99 sample c HAS storage. it exists.
> Now lets consider we have this "constant".
>
> struct X { int i; };
> void F(struct X* x) {}
> constant struct X c = { . i = 1 }; //no storage
>
> int main() {
> F(& (struct X) {.i = 1});
> F(&c); //what happens here?
> }
>
> When we call F(&c) some variable should be instantiated.?
>
> At the end it could work as enumerators work today
>
> enum { A = 1 };
> void F(int* i) {}
> void F2(int i) {}
> int main() {
> F(&A); //error: lvalue required as unary '&' operand
> F2(A); //OK
> }
>
> sometimes a local variable would be created, except for int double etc..
The reason why this features does not exist today may be because for complex
types we can create a const variable and reuse it.
and use defines for int double etc.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-10-28 22:54 +0100 |
| Message-ID | <slf67a$pu0$1@dont-email.me> |
| In reply to | #163205 |
On 28/10/2021 22:07, Thiago Adams wrote:
> On Thursday, October 28, 2021 at 5:57:38 PM UTC-3, Thiago Adams wrote:
>> in this C99 sample c HAS storage. it exists.
>> Now lets consider we have this "constant".
>>
>> struct X { int i; };
>> void F(struct X* x) {}
>> constant struct X c = { . i = 1 }; //no storage
>>
>> int main() {
>> F(& (struct X) {.i = 1});
>> F(&c); //what happens here?
>> }
>>
>> When we call F(&c) some variable should be instantiated.?
>>
>> At the end it could work as enumerators work today
>>
>> enum { A = 1 };
>> void F(int* i) {}
>> void F2(int i) {}
>> int main() {
>> F(&A); //error: lvalue required as unary '&' operand
>> F2(A); //OK
>> }
>>
>> sometimes a local variable would be created, except for int double etc..
>
> The reason why this features does not exist today may be because for complex
> types we can create a const variable and reuse it.
> and use defines for int double etc.
Below is a summary, in the first 3 Y/N columns, of the three different
ways C has to create named constants.
It's set up so that a Y response is the more desirable.
Here, enums tick nearly all the boxes, so that it is odd that #define
and const T seem more popular. But then, 'enum' was really intended for
other purposes (defining related names with incrementing values), so it
might itself seem odd to use it arbitrarily.
My 'constant' feature ticks all the boxes plus it doesn't look weird to use.
Characteristic #define const T enum 'constant'
Normal scope? N Y Y Y
Any numeric type? Y Y N Y
Avoids storage (5) Y N (3) Y Y
Use in non-VLA bounds Y N Y Y
Won't create a VLA? Y N Y Y
Use in static array bounds Y N Y Y
Use in switch-case labels Y N Y Y
Evaluate once (1) N Y Y Y
Prohibit & address-of Y N Y Y
Prohibit Pass by ref Y N Y Y
Impossible to modify? Y N (2) Y Y
Reduce const exprs? Y ? (3) Y Y
Unambiguous meaning (4) N Y Y Y
(1) With #define A ((B+C)*D) etc, at each place A is used, it will
expand that expression, and need to parse it and reduce, possibly 100s
of times
(2) It's possible to modify via casts
(3) Depends on compiler's optimisation abilities
(4) With #define, using the same ((B+C)*D) example each time A is
expanded, it will use whatever B, C, D names are in scope at that point,
potentially generating a different value of A each time.
(5) Apart from immediate operands, some hardware may require storage
for certain float operands for example. But this is not accessible to C
programs.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-10-28 15:37 -0700 |
| Message-ID | <875ytg22ty.fsf@nosuchdomain.example.com> |
| In reply to | #163205 |
Thiago Adams <thiago.adams@gmail.com> writes:
> On Thursday, October 28, 2021 at 5:57:38 PM UTC-3, Thiago Adams wrote:
[...]
>> At the end it could work as enumerators work today
>>
>> enum { A = 1 };
>> void F(int* i) {}
>> void F2(int i) {}
>> int main() {
>> F(&A); //error: lvalue required as unary '&' operand
>> F2(A); //OK
>> }
>>
>> sometimes a local variable would be created, except for int double etc..
>
> The reason why this features does not exist today may be because for complex
> types we can create a const variable and reuse it.
> and use defines for int double etc.
C's "const" keyword does not mean "constant", and it never has. Of
course the spelling is derived from the English word "constant", which
can cause some understandable confusion.
A *constant expression* is one that can be evaluated at compile time.
A *constant* is a literal.
The keyword "const" might more accurately have been spelled "readonly".
If a name is const-qualified, it means that the named object cannot be
modified via that name. Defining something as "const" never makes
its name a constant expression.
C++ added a special case, so that for example
const int n = 42;
makes the expression n a constant expression (though n is still an
object whose address can be taken). Later, C++ added the "constexpr"
keyword (like "const" but it requires the initializer to be constant),
which in my opinion would have been a better choice for this special
case.
Note that this:
const time_t now = time(NULL);
is perfectly legal; the expression t cannot even in principle be
evaluated at compile time. (`constexpr time_t now = time(NULL);`
is invalid in C++.)
I wouldn't mind seeing a future version of C adopt something like C++'s
"constexpr" -- *without* changing the current meaning of "const".
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-10-29 00:02 +0100 |
| Message-ID | <87lf2cvjm2.fsf@bsb.me.uk> |
| In reply to | #163210 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: > I wouldn't mind seeing a future version of C adopt something like C++'s > "constexpr" -- *without* changing the current meaning of "const". It's been proposed: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2851.pdf -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-10-28 22:10 +0100 |
| Message-ID | <87r1c4voru.fsf@bsb.me.uk> |
| In reply to | #163202 |
Thiago Adams <thiago.adams@gmail.com> writes: > On Thursday, October 28, 2021 at 4:56:18 PM UTC-3, Thiago Adams wrote: > ... >> > 'const' (as well as short, int, long, float, double, even static and >> > typedef) can occur anywhere, in any combination, in the declaration of a >> > base type (what goes on the left before the first variable). > > I also have a new definition for typedef considering how it works. > > We use to say typedef is a alias for a type name. "We"? The standard doesn't. It says the declaration defines a "typedef name". I agree it's handy to think of it as an alias, but you have to take care with analogies in technical situations. > But here , > > typedef int Int; > typedef unsigned Int T; //error > > Int does not work as a alias for int. An alias does not work in all contexts. I may be know as Shorty down the club, but I can't put that on my passport. Sometimes the "proper" name is needed. > So my definition is: > when we put typedef in a declaration we declare a variable that has no > storage. Well typedef is, syntactically, a storage class specifier like extern, static and register, so I can see why you might prefer that analogy. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-10-28 15:13 -0700 |
| Message-ID | <87a6is23xa.fsf@nosuchdomain.example.com> |
| In reply to | #163202 |
Thiago Adams <thiago.adams@gmail.com> writes:
> On Thursday, October 28, 2021 at 4:56:18 PM UTC-3, Thiago Adams wrote:
> ...
>> > 'const' (as well as short, int, long, float, double, even static and
>> > typedef) can occur anywhere, in any combination, in the declaration of a
>> > base type (what goes on the left before the first variable).
>
> I also have a new definition for typedef considering how it works.
>
> We use to say typedef is a alias for a type name.
>
> But here ,
>
> typedef int Int;
> typedef unsigned Int T; //error
>
> Int does not work as a alias for int.
Yes, it absolutely does. Given your first declaration, `Int` is an
alias for the *type* `int`, not for the *keyword* `int`. It's not a
macro, and it doesn't act like one.
The `unsigned` keyword can only be used as the syntax allows, and the
syntax doesn't allow it to be used with a typedef name. The `unsigned`
keyword can be used by itself as a type name, or along with the `char`,
`short`, `int`, and/or `long` keywords, as defined in N1570 6.7.2.
> So my definition is:
> when we put typedef in a declaration we declare a variable that has no
> storage.
No, that's not what it does. It doesn't declare a variable at all, with
or without storage, unless you stretch the meaning of "variable" almost
beyond recognition. (Note that the C standard doesn't use the term
"variable".). Rather, the `typedef` keyword is treated as a storage
class specifier for syntactic convenience.
> When we use this variable is the same of using typeof(variable) but
> we write just the variable name.
> Int x;
> So typedef is more like "use the same type of that variable here".
>
> considering this.... I was also considering to use typedef to define constants
>
> typedef double pi = 3.14;
> or
> valuedef double pi = 3.14;
>
> pi is a non-storage variable, but instead of copying its type
> we copy its initialization value.
>
> double x = pi;
That's more or less what `constexpr` does in C++, and what `const`
*almost* does in C. Using `typedef` for this would not in my opinion
make sense.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| Date | 2021-10-29 00:40 -0300 |
| Message-ID | <86ilxglcqj.fsf@levado.to> |
| In reply to | #163202 |
Thiago Adams <thiago.adams@gmail.com> writes: [...] > So my definition is: when we put typedef in a declaration we declare a > variable that has no storage. I don't like to say a variable that has no storage. Even the literal constants written in the body of your programs are loaded in memory and the place they occupy *is* storage. Of course, the whole idea that numbers represent themselves (and the fact that in languages like C we cannot get the address of literal number) encourages us to think like you do above, but I think that's not a very good idea.
[toc] | [prev] | [next] | [standalone]
| From | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| Date | 2021-10-28 23:48 -0300 |
| Message-ID | <86h7d0mtqp.fsf@levado.to> |
| In reply to | #163196 |
Bart <bc@freeuk.com> writes: > On 28/10/2021 16:50, Meredith Montgomery wrote: >> These seem legal declarations in C: >> const char msg[9] = "warming:"; >> char const msg[9] = "warming:"; >> What's the difference between them? > > There is no difference. You can even write: > > const char const msg[9]; > > > 'const' (as well as short, int, long, float, double, even static and > typedef) can occur anywhere, in any combination, in the declaration of > a base type (what goes on the left before the first variable). > > 'const' can also be repeated any number of times: > > char const const const const const const msg[9] > > if you want to be certain that msg is constant! > > However when applied to a pointer, then it must go after *. Very interesting. Thank you so much for this.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-10-28 13:04 -0400 |
| Message-ID | <slel67$ppc$1@dont-email.me> |
| In reply to | #163193 |
On 10/28/21 11:50 AM, Meredith Montgomery wrote:
> These seem legal declarations in C:
>
> const char msg[9] = "warming:";
> char const msg[9] = "warming:";
>
> What's the difference between them?
>
> (*) Note to self
>
> When I tried changing that array, the compiler did not let me to ---
> with either declaration. (So it appears there is no *effective*
> difference.)
>
> %cat msg.c
> #include <stdio.h>
>
> int main(void) {
>
> char const msg[9] = "warming:";
> msg[0]= 'f';
> printf("%s\n", msg);
>
> }
> %make msg
> gcc msg.c -o msg
> msg.c: In function 'main':
> msg.c:6:9: error: assignment of read-only location 'msg[0]'
> 6 | msg[0]= 'f';
> | ^
> make: *** [<builtin>: msg] Error 1
> %
>
"const" is a type qualifier. "char" is a type specifier. Both are
members of the larger category called "declaration specifiers". If you
have a string of declaration specifiers, they can occur in any order you
like, without any change of meaning.
[toc] | [prev] | [next] | [standalone]
| From | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| Date | 2021-10-29 00:34 -0300 |
| Message-ID | <86sfwkld1p.fsf@levado.to> |
| In reply to | #163197 |
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
> On 10/28/21 11:50 AM, Meredith Montgomery wrote:
>> These seem legal declarations in C:
>>
>> const char msg[9] = "warming:";
>> char const msg[9] = "warming:";
>>
>> What's the difference between them?
>>
>> (*) Note to self
>>
>> When I tried changing that array, the compiler did not let me to ---
>> with either declaration. (So it appears there is no *effective*
>> difference.)
>>
>> %cat msg.c
>> #include <stdio.h>
>>
>> int main(void) {
>>
>> char const msg[9] = "warming:";
>> msg[0]= 'f';
>> printf("%s\n", msg);
>>
>> }
>> %make msg
>> gcc msg.c -o msg
>> msg.c: In function 'main':
>> msg.c:6:9: error: assignment of read-only location 'msg[0]'
>> 6 | msg[0]= 'f';
>> | ^
>> make: *** [<builtin>: msg] Error 1
>> %
>>
>
> "const" is a type qualifier. "char" is a type specifier. Both are
> members of the larger category called "declaration specifiers". If you
> have a string of declaration specifiers, they can occur in any order you
> like, without any change of meaning.
That's a nice description. Thank you. I'm making the following
parallel in my mind:
type qualifier /is like/ an adjective
type specifier /is like/ a noun
(``Let c be /char/ming, but qualify it as unmovable.'')
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web