0

I was studying the Read-Only compound literals in C. And when I tried to change its value with the help of dereference operator, the value got changed!! I am now confused why is that so.

Also when I compiled and run the program (Without attempting to change its value) it shows this error:

Code_Testing.c:5:14: warning: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
    5 |     int *r = (const int[3]){6, 14, -98}; // Read Only compound Literal
      |

I cannot understand why it is ignoring the const qualifier.

I know that const qualifier discards any change, but here the value of the compound literal changed!

Can you please explain me where I had committed a mistake?

The program I wrote is this:

#include <stdio.h>

int main(void)
{
    int *r = (const int[3]){6, 14, -98}; // Read Only compound Literal
    *r += 99;
    printf("The changed value is = %d", *r);
    return 0;
}

The output is:

Code_Testing.c:5:14: warning: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
    5 |     int *r = (const int[3]){6, 14, -98}; // Read Only compound Literal
      |              ^
The changed value is = 105
  • *I know that `const` qualifier discards any change* Not when you throw it away by assignment or explicit casting. `const` in C is very weak - it wasn't even part of the language for quite some time. – Andrew Henle Dec 29 '20 at 14:42
  • What do you mean by “Read-Only compound literals”? Compound literals are not read-only in general, although they are if you define them with `const`. – Eric Postpischil Dec 29 '20 at 14:49

2 Answers2

2

You assign the const int[] array to a pointer to a non-const value. This means you as the programmer explicitly discard the const qualifyer. (The const on the right side actually does declare the literal as const.)

The compiler warns you about this.

To fix the warning you would have to use

const int *r = (const int[3]){6, 14, -98}; // Read Only compound Literal

Then you would get an error at the line

*r += 99;

where you want to modify the value.

The const qualifyer doesn't "discard any changes". As you can see, there are ways to modify the value. (But this is undefined behavior.)
The const qualifyer tells the compiler that the value should not be modified, and the compiler will show errors or warnings when your code would modify it or when it detects a use that could lead to modification of a value of const type.

Bodo
  • 9,287
  • 1
  • 13
  • 29
0

If you try to modify the value of a const-qualified object with an lvalue of non-const-qualified type, it's undefined behavior.

Quoting C11, chapter 6.7.3

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 assignment here discards the const-qualifier from the initializer, and assigns that to a non-const-qualified lvalue, so your compiler tried to warn you about the potential pitfall.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261