4

I was answering a question and made this test program.

#include <stdio.h>
int main()
{
    volatile const int v = 5;
    int * a = &v;
    *a =4;
    printf("%d\n", v);
    return 0;
}

Without the volatile keyword the code optimizes (compiled with -O3 apple clang 4.2) the change of the var away, with it works as expected and the const variable is modified correctly.

I was wondering if a more experienced C developer knows if there is a part of the standard that says this is unsafe or UB.

UPDATE: @EricPostpischil gave me this standards quote

A program may not modify its own object defined with a const-qualified type, per C 2011 (N1570) 6.7.3 6: “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.” An external agent may modify an object that has volatile-qualified type, per 6.7.3 7: “An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects

My program breaks the first rule but I thought that the second rule may exempt a program from the first.

UPDATE 2:

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously.134) What constitutes an access to an object that has volatile-qualified type is implementation-defined.

If you look at this quote you can see the var must be evaluated according to certain rules, I haven't read through all of section 5.1.2.3 but I believe that this may shed some light on the issue.

4
  • I'm sure this doesn't compile without errors. Commented Aug 5, 2013 at 18:11
  • @Devolus 1 warning, unless I left a typo in there Commented Aug 5, 2013 at 18:11
  • @Devolus in c99 standart, there is even an example thats almost equvalent to this one, and its noted as "may break the rule" not even a "breaks the rule" if I'd remember which rule it was, id look it up for you, but I'm sorry. but i was confused too and thought, That can't be without any errors. I tryed it.... and I was wondered... MSVC2010 compiler-> no warnings, no errors clang -> no error, 1 warning about something like "acces of not quallified type" or something. and gcc had also 0W/0E. Commented Aug 12, 2013 at 11:51
  • Why would you think 6.7.3.7 has any effect on 6.7.3.6? An assignment via a pointer is not "an external agent" or "modified in ways unknown to the implementation". Commented Feb 15, 2016 at 22:12

2 Answers 2

3

It is unsafe because the same behavior cannot be guaranteed for use in other compilers. So your code is compiler-dependent and may even be compiler switch dependent. That's why it's a bad idea.

Sign up to request clarification or add additional context in comments.

13 Comments

I agree with you in some respects but I also just tested it with g++ and it exhibited my expected behavior, hopefully someone can find a compiler where it doesn't work
That's not really the point. The point is someone could build a compiler in spec that didn't do that or allow for it. Then your code would break, perhaps sometime in the far future.
Yes but the point of my question is I believe even with the standards quote it is up for debate what the standard is implying, I'm not saying your wrong just that it is possible you are
I don't see the evidence that 6.7.3.7 is an invitation to violate 6.7.3.6
Well maybe you don't but I think it's possible it does, also I found a draft of the standard and I'm looking through it
|
0

This line:

int * a = &v;

is a constraint violation. The compiler must produce a diagnostic message, and may reject the program. If the compiler produces an executable anyway, then that executable has completely undefined behaviour (i.e. the C Standard no longer covers the program at all).

The constraints violated are that volatile nor const may not be implicitly converted away.

To comply with the C standard, the pointer must have its pointed-to type having the same or stronger qualifiers as the object being pointed to, e.g.:

int const volatile *a = &v;

after which you will find that the line *a = 4; causes a compilation error.


A possible attempt might be:

int *a = (int *)&v;

This line must compile, but then it causes undefined behaviour to read or write via *a. The undefined behaviour is specified by C11 6.7.3/6 (C99 and C89 had similar text):

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. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.

2 Comments

If both the original variable and the pointer are volatile qualified, a quality compiler that acknowledges the existence of hardware features it knows nothing about should assume that the programmer wants the behavior that will result from an attempt to store the indicated value to the indicated location. The Standard does not require that compiler writers acknowledge the existence of unknown hardware features, and relies upon compiler writers to exercise common sense in exposing such features to programmers. When using things like EEPROM, it is in fact useful...
...to have storage which is qualified as const volatile but then have functions which perform the necessary gymnastics to write it (which will, in many cases, include a write of the desired value to the desired address). I would be rather peeved at a compiler which forced any gymnastics beyond casting a pointer to uint8_t volatile* or uint32_t volatile* [depending upon hardware] to force it to generate the necessary write operation at the appropriate point in the sequence.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.