![]() |
casting const away
In a situation like this
void my_func(const FOO_T *); *foo = 'b'; my_func(foo); putchar(*foo); Is the compiler allowed to replace the second foo->a with 'b' i.e. allowed to assume that my_func does indeed not modify foo? I mean in C you one cast "const" away within said function. I wrote a test program who did just that, compiled with GCC -Wall -Wextra -ansi -pedantic -O3 : not even a warning and the compiler did not optimize the dereference away.. |
Re: casting const away
"copx" wrote in message news:ig3l22$3hb$1@speranza.aioe.org... >[snip] >Is the compiler allowed to replace the second foo->a with 'b' >i.e. allowed to assume that my_func does indeed not modify >foo? I mean in C you one cast "const" away within said function. >I wrote a test program who did just that, compiled with GCC >-Wall -Wextra -ansi -pedantic -O3 : not even a warning and >the compiler did not optimize the dereference away.. Wow, clc isn't what it used to be. In the good ol' days these group was so full of people who had memorized the C standard like Grand Ayatollahs the Quran that such a simple standard question was usually answered within minutes. Whatever, so I grabbed a draft copy of the standard and tried to figure it out myself. These documents really aren't written with end-users in mind, I tell you. However, after 10 minutes or so I arrived at the conclusion that this works and is guranteed to work because "const" is only really meaningful when it's applied to the "object" itself. I.e. a const pointer to something doesn't actually tell the compiler that the object pointed to is constant, this type of "constness" only exist to produce compiler warnings which may aid the programmer. By expliticly casting to a non-const pointer I get no warning because removing the "const" from the pointer just means.. telling the compiler not to produce a warning! |
Re: casting const away
On 01/ 6/11 06:47 PM, copx wrote:
> In a situation like this > > void my_func(const FOO_T *); > > *foo = 'b'; > my_func(foo); > putchar(*foo); > > Is the compiler allowed to replace the second foo->a with 'b' What second foo->a? You haven't shown a first, let alone a second. Without code your post does not make sense. -- Ian Collins |
Re: casting const away
"Ian Collins" wrote in message news:8oljqeFni5U11@mid.individual.net... On 01/ 6/11 06:47 PM, copx wrote: >> In a situation like this >> >> void my_func(const FOO_T *); >> >> *foo = 'b'; >> my_func(foo); >> putchar(*foo); >> >> Is the compiler allowed to replace the second foo->a with 'b' > >What second foo->a? You haven't shown a first, let alone a second. >Without code your post does not make sense. Oops, I simplified the code after writing the text below and forgot to update the text to reflect the change. "Second foo->a" should "Second *foo". -- Ian Collins |
Re: casting const away
"copx" wrote in message news:ig3l22$3hb$1@speranza.aioe.org... Here's some compile-ready code which illustrates the issue: #include <stdio.h> void foo(const int *c) { *((int *)c) = 'B'; } int main(void) { int a = 'A'; foo(&a); putchar(a); return 0; } ==== Result: no warnings, prints 'B'; As I wrote in the other post I think I have figured it out already. |
Re: casting const away
On 2011-01-06, copx <copx@gazeta.pl> wrote:
> In a situation like this > > void my_func(const FOO_T *); > > *foo = 'b'; > my_func(foo); > putchar(*foo); > > Is the compiler allowed to replace the second foo->a with 'b' > i.e. allowed to assume that my_func does indeed not modify > foo? I mean in C you one cast "const" away within said function. > I wrote a test program who did just that, compiled with GCC > -Wall -Wextra -ansi -pedantic -O3 : not even a warning and > the compiler did not optimize the dereference away.. The code has undefined behaviour. 6.7.3 5 If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. The compiler is not obliged to give a warning for undefined behaviour. |
Re: casting const away
copx <copx@gazeta.pl> wrote:
> > Here's some compile-ready code which illustrates the issue: > > #include <stdio.h> > > void foo(const int *c) > { > *((int *)c) = 'B'; > } > > > int main(void) > { > int a = 'A'; > > foo(&a); > putchar(a); > return 0; > } > > ==== > Result: no warnings, prints 'B'; It might just as well have printed 'A'. You have lied to the compiler by declaring that foo() does not modify what its argument points to but going ahead and doing so anyway. The compiler is permitted to believe the declaration but is not required to, so either result is acceptable. The code is not strictly conforming, but does not violate any constraints so no diagnostics are required. It also does not contain undefined behavior, just unspecified behavior. -- Larry Jones I keep forgetting that rules are only for little nice people. -- Calvin |
Re: casting const away
"Ike Naar" wrote in message news:slrn3vfsiibeu5.aj4.ike@iceland.freeshell.org. .. >The code has undefined behaviour. > >6.7.3 >5 If an attempt is made to modify an object defined with a >const-qualified type through use of an lvalue with non-const-qualified >type, the behavior is undefined. I read the same section of the standard and this doesn't support your statement IMO. The standard talks about OBJECTS with a const-qualified type NOT about const-qualified references to non-const-qualified objects. I.e. this only means that modifying a "const int" is undefined, const-qualified references to non-const-qualified objects aren't mentioned here. Digging further I could only find this: == const int *ptr_to_constant; ... The contents of anyobject pointed to by ptr_to_constant shall not be modified through that pointer, == Then I had to reference an entirely different section of the standard to figure out the technical definition of "shall not". ===== If a ‘‘shall’’or‘‘shall not’’requirement that appears outside of a constraint is violated, the behavior is undefined. === Ok,case finally solved, right? Unfortunately, no! The standard only says "through that pointer" notice the "that". I can copy the value of the const pointer to a non-const pointer and then use this newly created pointer to modify the object thus the object is never actually modified "through that pointer". The exact, literal meaning of what the standard says validates the behavior of GCC IMO, but the wording of the standard is so horribly confusing here that I wouldn't be surprised if other compilers interpret this mess in a different way. |
Re: casting const away
On 01/ 7/11 10:43 AM, copx wrote:
> > The standard only says "through that pointer" notice the "that". > I can copy the value of the const pointer to a non-const pointer > and then use this newly created pointer to modify the object thus > the object is never actually modified "through that pointer". Yes you can, but you have to lie to the compiler (cast) to do so. > The exact, literal meaning of what the standard says validates the > behavior of GCC IMO, but the wording of the standard is so horribly > confusing here that I wouldn't be surprised if other compilers interpret > this mess in a different way. The wording is clear: once you lie to the compiler you are in the land of undefined behaviour. -- Ian Collins |
Re: casting const away
christian.bau writes:
> Use "const int* restrict" instead: > > int i; const int* restrict p = &i; * (int *) p = 1; // Undefined > behaviour I don't believe that this will be an undefined behavior because p and (int*)p are both pointers to the same memory address hence there is no aliasing here. |
| All times are GMT. The time now is 02:28 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.