Lo standard C99 dice in 6.5.16: 2:
An assignment operator shall have a modifiable lvalue as its left operand.
e in 6.3.2.1:1:
A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.
Ora, consideriamo un% nonconst
struct
con un campo const
.
typedef struct S_s {
const int _a;
} S_t;
Per standard, il codice seguente è un comportamento non definito (UB):
S_t s1;
S_t s2 = { ._a = 2 };
s1 = s2;
Il problema semantico con questo è che l'entità che la racchiude ( struct
) dovrebbe essere considerata scrivibile (non di sola lettura), a giudicare dal tipo dichiarato dell'entità ( S_t s1
), ma non dovrebbe essere considerata scrivibile dal testo dello standard (le 2 clausole in alto) a causa del const
campo _a
. Lo standard rende poco chiaro per un programmatore che legge il codice che l'assegnazione è in realtà un UB, perché è impossibile dire che w / o la definizione di struct S_s ... S_t
tipo.
Inoltre, l'accesso in sola lettura al campo viene applicato solo sintatticamente in ogni caso. Non c'è alcun modo in cui alcuni campi di const
di% nonconst
% di co_de vadano realmente posizionati in una memoria di sola lettura. Ma una tale formulazione di standard mette fuori legge il codice che deliberatamente elude il struct
qualificatore di campi nelle procedure di accesso di questi campi, come in questo modo ( È una buona idea per qualificare i campi della struttura in C? ):
(*)
#include <stdlib.h>
#include <stdio.h>
typedef struct S_s {
const int _a;
} S_t;
S_t *
create_S(void) {
return calloc(sizeof(S_t), 1);
}
void
destroy_S(S_t *s) {
free(s);
}
const int
get_S_a(const S_t *s) {
return s->_a;
}
void
set_S_a(S_t *s, const int a) {
int *a_p = (int *)&s->_a;
*a_p = a;
}
int
main(void) {
S_t s1;
// s1._a = 5; // Error
set_S_a(&s1, 5); // OK
S_t *s2 = create_S();
// s2->_a = 8; // Error
set_S_a(s2, 8); // OK
printf("s1.a == %d\n", get_S_a(&s1));
printf("s2->a == %d\n", get_S_a(s2));
destroy_S(s2);
}
Quindi, per qualche motivo, per un intero const
a sola lettura è sufficiente dichiararlo struct
const S_t s3;
Ma per un intero const
non è un read-only, non è sufficiente dichiararlo senza struct
.
Quello che penso sarebbe meglio, è:
- Per limitare la creazione di strutture non%% co_de con i campi
const
e emettere una diagnostica in questo caso. Ciò renderebbe chiaro che ilconst
contenente i campi di sola lettura è di sola lettura. - Per definire il comportamento in caso di scrittura in un campo
const
appartenente a una struttura nonstruct
in modo da rendere il codice sopra (*) conforme allo standard.
Altrimenti il comportamento non è coerente e difficile da capire.
Quindi, qual è la ragione per cui C Standard considera in modo ricorsivo const
-ness, come lo mette?