So if I understand the author, const function arguments can just have const-ness cast away inside the function, so it's really much closer to a type hint than anything else. However, if a variable is declared const, casting away const-ness is undefined. Is this about right? Yikes that's complex. I suppose the moral is casting away const-ness is a terrible idea.
Const and Optimization in C
31–40 of 44 posts
Re: Const and Optimization in C
#32And with any kind of STL-like interface or container you're suddenly maintaining two duplicate versions of everything, a non-const version and a const version, likely along with a confusing pile of template metaprogramming and typedefs to support that. Avoiding const altogether is much cleaner.
As Casey Muratori (game programmer) once said, "I haven't typed "const" in over a decade, and I have had literally zero bugs that it would have caught."
Re: Const and Optimization in C
#33I've personally stopped using const in my C and C++ code, except for actually defining constants (in the #define sense). The headaches and complexity it introduces don't seem worth the benefit - you inevitably have to remove the const modifiers from your "const correct" function at some point when it needs to calls out to a non-const function you don't control (one that you know is 'logically const' and pure but does…
I think writing const-correct code where you can is useful. It helps document your code (for yourself and for others), it CAN catch issues (even if Casey Muratori claims it never helped), and it really isn't that hard to do (C routines don't need to be duplicated if you want to return non-const, like strstr, for example).
So what if you have to cast-away-const for interfacing to libraries which aren't const-correct? It still has benefits for your own code.
Re: Const and Optimization in C
#34Earlier quoted context omitted.
you skipped the first clause of my sentence -- if a variable is declared const, casting away const-ness is undefined is that not true?
Your first part was irrelevant: if you cast away const, of course variable must have been const in first place. As other have already mentioned, casting itself is not an undefined behavior (and sometimes even have legitimate reasons, mentioned in my earlier post). On the other hand, trying to modify const variable though non-const pointer is undefined behavior. P.S. if you downvoted to disagree with this (on my paren…
It seems highly non-intuitive to me that casting away constness works differently depending on whether the variable was defined const or not, but if that's the rules, that's the rules.
Re: Const and Optimization in C
#35Earlier quoted context omitted.
What is the argument in favor of specifically allowing casting away const of pointers?
- In some case implementing both "const" and "non const" methods cause a lot of code duplications and cast can help. - Compatibility with old libraries
D has an `inout` qualifier that has the effect of "transmitting" the const-ness of an argument to the return type.
Re: Const and Optimization in C
#36Earlier quoted context omitted.
`readonly_x` is a non-constant object of type 'pointer to const int'. If `readonly_x` itself was const-qualified, it'd look like this: `const int* const readonly_x`. This is a distinct object from whatever pointer the caller is passing in. But none of this matters to the special const rule -- that rule is not talking about the pointer object, but about the target object that the pointer is pointing to.
Thanks, that goes a long way toward an explanation. I'm still a bit surprised though that no compilers seem to complain even if we cast away the const from the properly const-qualified version. Here's the snippet I was playing with that tests all the variations: https://godbolt.org/g/aaC4B7 I should have expected it, but if you define the "lying" function where the compiler can see the full definition (and don't spec…
Re: Const and Optimization in C
#37Earlier quoted context omitted.
`readonly_x` is a non-constant object of type 'pointer to const int'. If `readonly_x` itself was const-qualified, it'd look like this: `const int* const readonly_x`. This is a distinct object from whatever pointer the caller is passing in. But none of this matters to the special const rule -- that rule is not talking about the pointer object, but about the target object that the pointer is pointing to.
Thanks, that goes a long way toward an explanation. I'm still a bit surprised though that no compilers seem to complain even if we cast away the const from the properly const-qualified version. Here's the snippet I was playing with that tests all the variations: https://godbolt.org/g/aaC4B7 I should have expected it, but if you define the "lying" function where the compiler can see the full definition (and don't spec…
Did you check out the link? https://godbolt.org/g/aaC4B7
My surprise is that none of clang, gcc, or icc give any warning on this with -Wall -Wextra:
1 void copy_const(const int * const arg) {
2 int *copy = (int *)arg;
3 (*copy)++;
4 }
I agree that the cast on line 2 is legal and requires no warning. My surprise is that there is no warning for the write on line 3, since I think this is undefined behavior according the quoted part of the spec. Isn't this trying "to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type"?I realize that the compiler has no obligation to issue a warning here, and in fact is fully entitled to my first-born as soon as it encounters undefined behavior. Still, it seems like it would be a useful place to offer the user a warning just as it does in the case of direct modification:
1 void write_const(const int * const arg) {
2 (*arg)++;
3 }
clang: "error: read-only variable is not assignable"gcc: "error: increment of read-only location '*arg'"
icc: "error #137: expression must be a modifiable lvalue"
Re: Const and Optimization in C
#38Earlier quoted context omitted.
What is the argument in favor of specifically allowing casting away const of pointers?
The strongest argument is to support a sort of poor man's const-generics. Consider a function like strchr(). This locates a character in a (const) string, and returns a (non-const) pointer to it. The idea is that you can use this on both const and non-const strings. Call it on a const string, you get back a non-const pointer (which you better treat as const!) But call it on a non-const string, you get back a non-cons…
Re: Const and Optimization in C
#39Earlier quoted context omitted.
Thanks, that goes a long way toward an explanation. I'm still a bit surprised though that no compilers seem to complain even if we cast away the const from the properly const-qualified version. Here's the snippet I was playing with that tests all the variations: https://godbolt.org/g/aaC4B7 I should have expected it, but if you define the "lying" function where the compiler can see the full definition (and don't spec…
[Saw a response here, but it disappeared before my reply. Posted here anyway in case it clarifies my first paragraph.] Did you check out the link? https://godbolt.org/g/aaC4B7 My surprise is that none of clang, gcc, or icc give any warning on this with -Wall -Wextra: 1 void copy_const(const int * const arg) { 2 int *copy = (int *)arg; 3 (*copy)++; 4 } I agree that the cast on line 2 is legal and requires no warning.…
Re: Const and Optimization in C
#40Wtf? This seems like a huge potential optimization gain missed. Surely by know it can't just be enabled because a lot of code would be written with the assumption above, I'm just curious for the rationale of this model. I don't understand the reasoning at all, why would you ever want to cast from a const to non const and have the behaviour depend on the type I pass to the function? Let's assume the signature of foo was faulty definied as const but still modifies x inside (faulty definined signatures for API compatibility seems to be the whole reason for allowing you to cast away const) and I pass int x, the the behaviour is definied but if I pass a const int x the behaviour is undefined?!? Clearly this is the fault of the person writing the foo function but how does that help me writing the bar function, I am not expected to know the whole call stack of foo, that's what the signature is for, I must be able to trust it's const correctness and that should not depend on what I pass into it.
If the optimization was always disabled I could understand the reasoning but now you get some kind of half assed middle ground where you as a caller must guarantee the actions of a callee.