0

If I have the following code:

  struct point
    {
        int x;
        int y;
    };

    const struct point p = {1, 2};
    p.x = 3;

The compiler gives me an error: "assignment of member 'x' in read only object"

I'm wondering what happens when I declare a const struct.

Does all the members inherit const, or only the variable p is read-only and for this its members are not accessible?

10
  • What would it mean for the structure to be const and its members not? Would the compiler give you a warning if you attempted to assign the entire structure at once but not if you attempted to assign individual members? Would that be useful? Commented Jan 27 at 18:26
  • "Does all the members inherit const, or only the variable p is read-only?" I don't understand the question. Clearly the members themselves can't be modified, as you've tested yourself. Commented Jan 27 at 18:26
  • What you're doing is equivalent to const int i = 5;. You do know that the variable i will then be a constant, and you can't modify the value of i? It's the same here: You define p as a constant object. It might be easier if we introduce a type-alias for the structure: typedef struct point point_type;. Then you can do const point_type p = { 1, 2 };. Is that easier to understand? Commented Jan 27 at 18:32
  • @HolyBlackCat, I wrote my question not very well, so I edited it again Commented Jan 27 at 19:21
  • @xdevel2000 Doesn't my answer answer your question, if not do let me know what are you actually trying to ask? Commented Jan 27 at 19:22

4 Answers 4

4

C 2024 6.5.3.4 discusses the operators for accessing structure and union members, . and ->. For . it says:

… If the first expression has qualified type, the result has the so-qualified version of the type of the designated member…

Therefore, when p is a const-qualified structure, the type of p.x is const-qualified.

For -> it has similar but suitably modified wording:

If the first expression is a pointer to a qualified type, the result has the so-qualified version of the type of the designated member.

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

10 Comments

I think this is the correct answer as the specification says. My doubt is bacause the error reported by the compiler that says: "assignment of member 'x' in read only object and not that x is a const object
@xdevel2000, "read only" is precisely what const means. Perhaps you're thinking that it means the value of the object cannot change, but that's not so in general.
@JohnBollinger: That is not what “precisely” means. const does not mean precisely “read only.” In fact, it effectively has two meanings. One is that, in assignments and other operations that modify an object, the compiler must warn you if the type is const-qualified. It does not mean the object is read only. A second is that, for an object defined with const, the standard does not define the behavior of a program that attempts to modify the object. (It is not necessarily read-only. A C implementation could support writing.) These could be written up further, as they are different…
… For the latter, when an object is defined with const, its members must necessarily be const in the same way, because any modification of a member modifies the object, and therefore the behavior is not defined. For the former, the fact the members are const is separate from the fact the structure type is const; the application of const to the members is conveyed only by the separate rule in the standard that I cited; it is not an inherent part of the specification of declaring a type to be const. So the semantics are complicated, and const does not mean precisely “read only.”
@EricPostpischil, reading the specification at C 2024 6.5.3.4 it cited the term "qualified type" and in fact const is a type qualifier. So if I instead use constexpr that is a storage-class specifer, does the rules also apply? (do a specifier also "qualify" structure members?)
|
2

Does all the members inherit const, or only the variable p is read-only?

The whole object is const and you can't modify it. As the whole object is const then by definition all its members are const too.

If you want to have only some members const:

  struct point
    {
        int x;
        const int y;
    };

Comments

1

If your background is Java or C#, you're used to all objects being on the heap, and the variable such as p is only a reference to the object. Meaning that p can be changed independently of the internal fields of p (p.x, p.y).

A structure in C (and C++) is on the stack like other local variables, and so p.x and p.y are simply stack variables with p as a prefix.

So while final p in Java only modifies p, while the internal fields are still mutable, const p in C modifies the fields because there is no separate p variable.

If you were to declare p as a pointer, then it is now a separate variable and you can also declare it constant:

/* const modifies "struct point",
   p1 can be changed but p1->x and p1->y can't */
const struct point * p1 = malloc(sizeof(structure point));
p1.x = 1;   // Compile error.
p1 = NULL;  // Okay.

/* First const modifies "struct point", second modifies p2,
   so neither p2, p2->x, or p2->y can be changed */
const struct point * const p2 = malloc(sizeof(structure point));
p1.x = 1;   // Compile error.
p2 = NULL;  // Compile error.

/* const modifies p3,
   p3->x and p3->y can be changed but p3 can't. */ 
struct point * const p3 = malloc(sizeof(structure point));
p1.x = 1;   // Okay.
p3 = NULL;  // Compile error.

2 Comments

You are writing about pointers, which have nothing in common with the OP's question.
@0___________, this answer addresses a possible source of the uncertainty behind the OP's question, and the question reads very oddly to me unless I suppose that the OP has a misunderstanding along the lines discussed here. This answer would be improved by clarifying and better calling out its currently oblique response to the question posed, but even without that, it is definitely related to the question.
0

Does all the members inherit const, or only the variable p is read-only and for this its members are not accessible?

The members don't inherit anything. You have marked the variable declaration as const, so you can only initialize in the initialization itself. The const qualifier can be applied to the fields themselves, if you want them not to be modified in the code.

Just assume that something that has been qualified const is not assignable (you can initialize it at declaration, as you do in your sample code, but never after that) You could have qualified e.g.

struct point {
    const char * const name;
    int x, y;
};

and then use:

struct point var = { .name = "origin", .x = 0, .y = 0 };

now you can

   var.x = 3;  var.y = 5;

but not

    var.name = "not the origin anymore";

because name is a const qualified field.

And of course, if you declare:

   const struct point origin = { "origin", 0, 0 };

the whole variable is const and you cannot change it at all.

Comments

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.