Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
604 views
in Technique[技术] by (71.8m points)

c - Can we modify the value of a const variable?

From this article.

Another use for declaring a variable as register and const is to inhibit any non-local change of that variable, even trough taking its address and then casting the pointer. Even if you think that you yourself would never do this, once you pass a pointer (even with a const attribute) to some other function, you can never be sure that this might be malicious and change the variable under your feet.

I don't understand how we can modify the value of a const variable by a pointer. Isn't it undefined behavior?

const int a = 81;
int *p = (int *)&a;
*p = 42; /* not allowed */
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The author's point is that declaring a variable with register storage class prevents you from taking its address, so it can not be passed to a function that might change its value by casting away const.

void bad_func(const int *p) {
    int *q = (int *) p;            // casting away const
    *q = 42;                       // potential undefined behaviour
}

void my_func() {
    int i = 4;
    const int j = 5;
    register const int k = 6;
    bad_func(&i);                  // ugly but allowed
    bad_func(&j);                  // oops - undefined behaviour invoked
    bad_func(&k);                  // constraint violation; diagnostic required
}

By changing potential UB into a constraint violation, a diagnostic becomes required and the error is (required to be) diagnosed at compile time:

5.1.1.3 Diagnostics

1 - A conforming implementation shall produce at least one diagnostic message [...] if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined.

6.5.3.2 Address and indirection operators

Constraints

1 - The operand of the unary & operator shall be [...] an lvalue that designates an object that [...] is not declared with the register storage-class specifier.

Note that array-to-pointer decay on a register array object is undefined behaviour that is not required to be diagnosed (6.3.2.1:3).

Note also that taking the address of a register lvalue is allowed in C++, where register is just an optimiser hint (and a deprecated one at that).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...