C 2018 6.3.2.1 2 says qualifiers such const are removed when any object is used for its value in an expression:
Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. If the lvalue has qualified type, the value has the unqualified version of the type of the lvalue; additionally, if the lvalue has atomic type, the value has the non-atomic version of the type of the lvalue; otherwise, the value has the type of the lvalue.
Thus, in xx = (const struct x) {0};, (const struct x) {0}; is a compound literal that creates a const struct x object. However, in taking the value of this object, const is removed, and the result is a struct x value. (The “value” of a structure is the aggregate of the values of all its members.)
Thus, in this use, the const ultimately has no effect. However, the compound literal does create a const object. The effect of this could be seen in other uses. For example, with const struct x *p = & (const struct x) {0};, we take the address of the compound structure. Then if we attempt to remove const and modify the structure, as with ((struct x *) p)->a = 3;, the behavior is not defined by the C standard. The compiler could have placed the structure in read-only memory, and attempting to modify it could generate a trap. Or, during optimization, the compiler could have used the fact that the structure is const to ignore any possibility it could change. For example, in:
const struct *p = & (const struct x) {0};
((struct x *) p)->a = 3;
printf("%d\n", p->a);
the program might print “0” because in the p->a in the printf, the compiler uses the fact that p->a is defined to be a const zero.