|
|||
|
On 06/ 4/12 11:52 AM, BartC wrote:
> > > "Ian Collins"<ian-news@hotmail.com> wrote in message > news:a32adaF5maU6@mid.individual.net... >> On 06/ 4/12 11:23 AM, BartC wrote: > >>> Would a const attribute be any use here: >> >> Yes, change it and see: >> >> void changestr(const char* s) >> >> gcc x.c >> x.c: In function ‘changestr’: >> x.c:5:3: error: assignment of read-only location ‘*s’ > > But then I can't use changestr() for it's intended purpose! Ah, I see your point. The rest of my reply still applies! >> That's the "glorious mess" I mentioned up-thread. >> >> C++ fixed this one, but I'm sure if the C committee tries, the fossils >> would pop up and whine about breaking existing (already broken) code. > > In the meantime, coding seems simpler without bothering with 'const' all. Or find a compiler option that does the check. -Wwrite-strings does the trick for gcc. -- Ian Collins |
|
|
||||
|
||||
|
|
|
|||
|
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> בתאריך יום ראשון, 3 ביו*י 2012 21:49:19 UTC+1, מאת Ben Bacarisse: >> Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >> >> > I never use it. Part of the reason is that whilst int member(const FOO >> > *obj) is clear enough in intention, in fact the constness of obj does >> > not extend to its members. >> >> Can you say what you mean by this? It contradicts what I thought was >> the case (assuming you meant the members of *obj). >> > typedef struct > { > char *name; > } EMPLOYEE; > > const char *getname(const EMPLOYEE *employee) > { > strcpy(employee->name, "Fred"); > return employee->name; > } What's that got to do with what you said? The object being modified by strcpy is not a member of *employee. -- Ben. |
|
|||
|
Ian Collins <ian-news@hotmail.com> writes:
> On 06/ 4/12 10:47 AM, BartC wrote: >> "Ian Collins"<ian-news@hotmail.com> wrote in message <snip> >>> If a function doesn't modify a parameter, declare it const. What's so >>> hard about that? >> >> Because nineteen times out of twenty, it won't modify it, so it means loads >> of const attributes cluttering up code. >> >> Of course some parameter types can be harmlessly modified (ints for >> example), and const isn't necessary, but then you have to start thinking >> about about every parameter and whether it will be modified in the caller or >> in the callee. > > Isn't that part of the design process? Naturally it's pointless > declaring a value type parameter const, but pointer types should > be. A minor point... You keep talking about declaring parameters const when a function does not modify them (and now BartC has taken you at your word) but you are not, I think, talking about const parameters, nor about pointer parameters being const, (as above), but about parameters that are pointers to const types. I know that "a const pointer" is a commonly used phrase, but it can be really confusing because it's literally not what is usually meant. <snip> -- Ben. |
|
|||
|
On 06/ 4/12 12:33 PM, Ben Bacarisse wrote:
> Ian Collins<ian-news@hotmail.com> writes: > >> On 06/ 4/12 10:47 AM, BartC wrote: >>> "Ian Collins"<ian-news@hotmail.com> wrote in message > <snip> >>>> If a function doesn't modify a parameter, declare it const. What's so >>>> hard about that? >>> >>> Because nineteen times out of twenty, it won't modify it, so it means loads >>> of const attributes cluttering up code. >>> >>> Of course some parameter types can be harmlessly modified (ints for >>> example), and const isn't necessary, but then you have to start thinking >>> about about every parameter and whether it will be modified in the caller or >>> in the callee. >> >> Isn't that part of the design process? Naturally it's pointless >> declaring a value type parameter const, but pointer types should >> be. > > A minor point... > > You keep talking about declaring parameters const when a function does > not modify them (and now BartC has taken you at your word) but you are > not, I think, talking about const parameters, nor about pointer > parameters being const, (as above), but about parameters that are > pointers to const types. I am, thank you for the clarification. -- Ian Collins |
|
|||
|
"BartC" <bc@freeuk.com> writes:
<snip> > Would a const attribute be any use here: > > #include <stdio.h> > #include <string.h> > > void changestr(char* s){ > s[0]='?'; > } > > int main(void) > { > changestr("abcdef"); > puts("abcdef"); > } > > I want to able to use changestr() to modify a string variable. But how > can I stop a string literal being passed (which will either corrupt > the literal, or will crash, on my tests)? > > It's possible the new write-attribute I mentioned a couple of posts > ago (eg. 'var' to mean the opposite of 'const') could be useful > here. Then the compiler knows passing the string literal is a mistake. > > (And I can't find a gcc warning level to tell me that a string literal > is being passed as a non-const char* parameter which could potentially > overwrite it.) "gcc -Wwrite-strings" makes string literals const (and thus the resulting pointer becomes a const char *). This is how C++ treats strings. It has the curious side effect of making gcc non-conforming even with all the right other options (-std=c99 -pedantic). The reason is far too obscure to worry about in practice. I find it a very useful option. -- Ben. |
|
|||
|
בתאריך יום ש*י,4 ביו*י 2012 00:14:38 UTC+1, מאת Ian Collins:
> On 06/ 4/12 11:04 AM, Malcolm McLean wrote: > > There's a good example of the confusion, does it modify the triangle or > not? From the description you give, it looks like if does not in either > case. > > It is very much the callers business to know whether the triangle it > passes will or will not be molested by the function. What if it has a > table of triangles in read only memory? > I didn't tell you how the triangle was passed, whether as a structure, buffer, or set of separate parameters. Generally you know whether the triangle will be molested or not. If the engine needs some temporay state, then the triangle structure will have members with names like "reserved_flag" and so on. What's much more likely is that the engine doesn't buffer the triangle vertices independently. It just keeps a pointer to them. If you over-write the vertices before you call the frame synch, you'll get the wrong triangle. But const won't help you with that. With the ENGINE parameter, you don't know whether drawing a triangle affects the state or not, nor should you. And that's a common paradigm. const breaks the paradigm here. |
|
|||
|
"Keith Thompson" <kst-u@mib.org> wrote in message
news:lny5o4dsqr.fsf@nuthaus.mib.org... > "BartC" <bc@freeuk.com> writes: >> why ... didn't someone just add a feature like: >> >> constant int d = 4000; > In fact someone did do that: Bjarne Stroustrup, when he was designing > C++. > > Except that he didn't introduce a new keyword; he just tweaked the > semantics of "const". > > In C++, if you declare > > const some_type x = init_expr; > > x becomes a constant expression *if* some_type is arithmetic *and* > init_expr is a constant expression. Otherwise, it has pretty much the > same meaning it has in C. (I probably haven't gotten that 100% right, > but that's the general idea.) It's taking a slightly tricky concept, a 'const' attribute, and making it even harder. Now it means read-only variables, read-only parameters, *and* named literals. Provided it can be agreed whether a particular right-hand expression is a constant or not; some compilers might be clever enough to evaluate the results of certain functions, others won't. And it's still not clear whether they are allowed as l-values or not. Although I suppose, compared with the rest of C++, no-one would really notice.. Using a new keyword and a new concept would keep things simple: it would only be used to apply a type and name to a literal. The right-hand-size *must* be a constant (on any compiler). You can't use them as l-values. And it would almost be the same as using the literal itself (the declaration may introduce a cast). However it would only make sense for primitives: values that could correspond to 'immediate' data in machine code, and which don't need any storage reserved. A named string literal doesn't work as well (as it would still need storage). -- Bartc |
|
|||
|
Am 04.06.2012 13:20, schrieb BartC:
> "Keith Thompson" <kst-u@mib.org> wrote in message > news:lny5o4dsqr.fsf@nuthaus.mib.org... >> "BartC" <bc@freeuk.com> writes: > >>> why ... didn't someone just add a feature like: >>> >>> constant int d = 4000; > >> In fact someone did do that: Bjarne Stroustrup, when he was designing >> C++. >> >> Except that he didn't introduce a new keyword; he just tweaked the >> semantics of "const". >> >> In C++, if you declare >> >> const some_type x = init_expr; >> >> x becomes a constant expression *if* some_type is arithmetic *and* >> init_expr is a constant expression. Otherwise, it has pretty much the >> same meaning it has in C. (I probably haven't gotten that 100% right, >> but that's the general idea.) > > It's taking a slightly tricky concept, a 'const' attribute, and making it > even harder. Now it means read-only variables, read-only parameters, *and* > named literals. Provided it can be agreed whether a particular right-hand > expression is a constant or not; some compilers might be clever enough to > evaluate the results of certain functions, others won't. And it's still not > clear whether they are allowed as l-values or not. agreed > Although I suppose, compared with the rest of C++, no-one would really > notice.. ![]() > Using a new keyword and a new concept would keep things simple: it would > only be used to apply a type and name to a literal. The right-hand-size > *must* be a constant (on any compiler). You can't use them as l-values. And > it would almost be the same as using the literal itself (the declaration > may introduce a cast). No I don't think that a new keyword would be needed. Alowing const qualified register "variables" in file scope would do the trick. register struct toto const A = { .x = 42 }; would give you real literals for almost any data type. For such variables no aliasing is possible (no one can take their adress) and so they can be considered as real constants. They could easily be declared-defined in any header file since they wouldn't need to generate an external symbol. Jens |
|
|||
|
On 06/03/2012 10:39 AM, Malcolm McLean wrote:
.... > ... Part of the reason is that whilst int member(const FOO *obj) is clear enough in intention, in fact the constness of obj does not extend to its members. A compiler for which that was the case would be non-conforming. It violates 6.5.2.3p4: "A postfix expression followed by the -> operator and an identifier designates a member of a structure or union object. .... If the first expression is a pointer to a qualified type, the result has the so-qualified version of the type of the designated member." Can you provide an example of a compiler claiming to conform to the C standard which treats a member of *obj as though it was not const-qualified? |
|
|||
|
In article <jqgpig$plu$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
>"Ian Collins" <ian-news@hotmail.com> wrote in message >news:a327a6F5maU3@mid.individual.net... >> >> If a function doesn't modify a parameter, declare it const. What's so >> hard about that? > >Because nineteen times out of twenty, it won't modify it, so it means loads >of const attributes cluttering up code. The omission of const qualifiers clutters the code with spurious requests for write access. const-as-default for pointer target types is a good idea. It would be nice to have it in the language, but the next best thing is to have it in your coding style. -- Alan Curry |
|
|||
|
"BartC" <bc@freeuk.com> writes:
> "Keith Thompson" <kst-u@mib.org> wrote in message > news:lny5o4dsqr.fsf@nuthaus.mib.org... >> "BartC" <bc@freeuk.com> writes: > >>> why ... didn't someone just add a feature like: >>> >>> constant int d = 4000; > >> In fact someone did do that: Bjarne Stroustrup, when he was designing >> C++. >> >> Except that he didn't introduce a new keyword; he just tweaked the >> semantics of "const". >> >> In C++, if you declare >> >> const some_type x = init_expr; >> >> x becomes a constant expression *if* some_type is arithmetic *and* >> init_expr is a constant expression. Otherwise, it has pretty much the >> same meaning it has in C. (I probably haven't gotten that 100% right, >> but that's the general idea.) > > It's taking a slightly tricky concept, a 'const' attribute, and making it > even harder. Now it means read-only variables, read-only parameters, *and* > named literals. Variables and parameters are both objects, and "const" means the same thing for both, so it's not as tricky as you imply. > Provided it can be agreed whether a particular right-hand > expression is a constant or not; some compilers might be clever enough to > evaluate the results of certain functions, others won't. And it's still not > clear whether they are allowed as l-values or not. The C standard defines "constant expressions" unambiguously in section 6.6. A constant expression isn't merely an expression that some particular compiler is able to evaluate at compile time. The C++ standard does make it perfectly clear whether such constants are allowed as lvalues. (I haven't found the relevant wording in the C++ standard, but g++ -pedantic allows it.) > Although I suppose, compared with the rest of C++, no-one would really > notice.. > > Using a new keyword and a new concept would keep things simple: it would > only be used to apply a type and name to a literal. The right-hand-size > *must* be a constant (on any compiler). You can't use them as l-values. And > it would almost be the same as using the literal itself (the declaration may > introduce a cast). Using the same mechanism that's been used in C++ for years would keep things even simpler. I certainly don't argue that C should adopt C++ features wholesale, but in this case the way C++ does it is good enough, and *unnecessary* incompatibilities are, well, unnecessary. [...] -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Will write code for food. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
|
|||
|
In article <39346056-1528-4667-85d2-a860b6ba018a@googlegroups.com>,
Malcolm McLean <malcolm.mclean5@btinternet.com> wrote: >Part of the reason is that whilst int member(const FOO *obj) is clear >enough in intention, in fact the constness of obj does not extend to >its members. know what you meant The problem is that people often want a 'semantic' const. For example: struct bar { int bar_color; char *bar_name; struct whiz *bar_whiz; }; struct const_bar { const int bar_color; const char *bar_name; const struct whiz *bar_whiz; }; At first it looks like i made all the members 'const', but of course that's not true. |
|
|||
|
Les Cargill <lcargill99@comcast.com> writes:
> I am using Mingw 3.4.5 on a 'Doze box, but it pretty much > follows any Gnu compiler I've run into. > > Why is this: > > --------------------------- > #define SIZE 20 > const int size = SIZE; > char array[SIZE]; > --------------------------- > > legal, yet > > --------------------------- > #define SIZE 20 > const int size = SIZE; > char array[size]; > --------------------------- > > not? > > The int size is invariant, and ... "morally" > equivalent to using SIZE, yet it won't let me do that. > > And yes, I understand/speak/grok preprocessor vs. > compiler. I know *how*, I just wonder *why*. Is > this a practical, strategic or tactical thing, > or am I just being silly? Was it a conscious decision > of the committee, or just one of those things? I would like to offer some contrasting opinions to those of Ian Collins (and no disrepect intended, I just have some different views to suggest). At the time C was first standardized, I don't think any C implementations had this capability. (I was working actively in C++ during this time, and I don't remember C++ having it either.) Whether it was considered or not, the committee chose to be cautiously conservative and not include such a rule in the Standard, and IMO that was an apppropriate policy at that time. Subsequently, I suspect it wasn't added for some combination of (a) no one proposing/championing it, (b) little or no experience with C implementations that offer it, and / or (c) no perception of any significant demand. Personally I would tend to side with those in category (c). As language features go this one doesn't offer very much. I know a lot of people don't like the C preprocessor, but except for that I don't see any significant benefit from providing this capability. Why complicate the language definition needlessly? Incidentally, note that the Standard actually does allow implementations to accept the example code without complaint, under paragraph 10 of the section on Constant Expressions. (Some other people who post in c.l.c don't agree with this conclusion; note however that gcc's behavior, to give one example, agrees with my assessment.) Despite having the freedom to accept this construct, I'm not aware of any implementations (of C) that do. That probably means there haven't been a lot of people clamoring for it. |
|
|||
|
Tim Rentsch wrote:
> Les Cargill <lcargill99@comcast.com> writes: > >> I am using Mingw 3.4.5 on a 'Doze box, but it pretty much >> follows any Gnu compiler I've run into. >> >> Why is this: >> >> --------------------------- >> #define SIZE 20 >> const int size = SIZE; >> char array[SIZE]; >> --------------------------- >> >> legal, yet >> >> --------------------------- >> #define SIZE 20 >> const int size = SIZE; >> char array[size]; >> --------------------------- >> >> not? >> >> The int size is invariant, and ... "morally" >> equivalent to using SIZE, yet it won't let me do that. >> >> And yes, I understand/speak/grok preprocessor vs. >> compiler. I know *how*, I just wonder *why*. Is >> this a practical, strategic or tactical thing, >> or am I just being silly? Was it a conscious decision >> of the committee, or just one of those things? > > I would like to offer some contrasting opinions to those of > Ian Collins (and no disrepect intended, I just have some > different views to suggest). > > At the time C was first standardized, I don't think any C > implementations had this capability. (I was working > actively in C++ during this time, and I don't remember C++ > having it either.) Whether it was considered or not, the > committee chose to be cautiously conservative and not > include such a rule in the Standard, and IMO that was an > apppropriate policy at that time. > > Subsequently, I suspect it wasn't added for some combination > of (a) no one proposing/championing it, (b) little or no > experience with C implementations that offer it, and / or > (c) no perception of any significant demand. > > Personally I would tend to side with those in category (c). > As language features go this one doesn't offer very much. It really doesn't offer much. The only reason I asked is because there's been a gradual movement away from K&R to ..... something else. > I know a lot of people don't like the C preprocessor, I am not one of them. In lots of cases, I *prefer* it. Attempts to eliminate the preprocessor are generally somewhat/somehow worse than what they replace. > but > except for that I don't see any significant benefit from > providing this capability. Why complicate the language > definition needlessly? > The only "why" is that you now have two thingies - one's a macro, one's a const object, and they have slightly different semantics, despite me wanting them to be the same thing ![]() It's by no means a huge problem. > Incidentally, note that the Standard actually does allow > implementations to accept the example code without > complaint, under paragraph 10 of the section on Constant > Expressions. (Some other people who post in c.l.c don't > agree with this conclusion; note however that gcc's > behavior, to give one example, agrees with my assessment.) > Despite having the freedom to accept this construct, I'm not > aware of any implementations (of C) that do. That probably > means there haven't been a lot of people clamoring for it. > -- Les Cargill |
|
|||
|
Les Cargill <lcargill99@comcast.com> writes:
> Tim Rentsch wrote: >> Les Cargill <lcargill99@comcast.com> writes: >> >>> I am using Mingw 3.4.5 on a 'Doze box, but it pretty much >>> follows any Gnu compiler I've run into. >>> >>> Why is this: >>> >>> --------------------------- >>> #define SIZE 20 >>> const int size = SIZE; >>> char array[SIZE]; >>> --------------------------- >>> >>> legal, yet >>> >>> --------------------------- >>> #define SIZE 20 >>> const int size = SIZE; >>> char array[size]; >>> --------------------------- >>> >>> not? >>> >>> [snip] >> ... I don't see any significant benefit from >> providing this capability. Why complicate the language >> definition needlessly? >> > > The only "why" is that you now have two thingies - one's > a macro, one's a const object, and they have slightly > different semantics, despite me wanting them to be the same > thing [snip]I suggest that there are at least a couple of other reasons. First is that the new method would need to be documented in the Standard. Readers of the Standard know that many aspects that are seemingly simple take an inordinate amount of description (and discussion about what the description should be) to specify. In other words there is work involved to do it, and the committee has plenty of other, more important, things to keep them busy. Second is that if such a capability were put in, it's only a matter of time before someone wants a "natural" extension to handle other possible cases. For example, what about this: const int size; char array[size]; ... const int size = 20; This should be easy to implement; why not have it (or so the argument would go)? For another example, what about this: extern const int size; char array[size]; ... and in another translation unit const int size = 20; This also shouldn't be too hard to implement. It needs more elaborate linker technology, but given what all else relocating linker/loaders do, that isn't too much of a stretch. I'm not trying to say that such arguments would be convincing; only that suggestions like these would be made (and arguments to go with them). Once the door is opened, it's almost for sure that some people will want to open it farther. Better not to open the door in the first place. |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|