C99 표준은 6.5.16 : 2에 나와 있습니다.
할당 연산자는 왼쪽 피연산자로 수정 가능한 lvalue를 가져야합니다.
그리고 6.3.2.1:1에서 :
수정 가능한 lvalue는 배열 유형이없고 불완전한 유형이 없으며 const 한정 유형이 없으며 구조 또는 공용체 인 경우 멤버를 포함하지 않는 lvalue입니다 (재귀 적으로 모든 멤버 포함) const 한정 유형의 모든 포함 된 집계 또는 공용체의 요소).
이제, 비 살펴 보자 const
struct
A의 const
필드.
typedef struct S_s {
const int _a;
} S_t;
기본적으로 다음 코드는 정의되지 않은 동작 (UB)입니다.
S_t s1;
S_t s2 = { ._a = 2 };
s1 = s2;
이것의 의미 론적 문제는 엔 클로징 엔티티 ( struct
)가 선언 된 엔티티 유형 ()으로 판단하여 쓰기 가능 (읽기 전용 S_t s1
이 아닌) 것으로 간주되어야하지만 표준의 문구 (2 절)에 의해 쓰기 가능한 것으로 간주되어서는 안된다는 것입니다 const
필드로 인해) _a
. 표준은 프로그래머가 코드를 읽는 것이 할당이 실제로 UB라는 것을 불분명하게 만듭니다 struct S_s ... S_t
. 유형 의 정의없이 말할 수 없기 때문 입니다.
또한, 필드에 대한 읽기 전용 액세스는 어쨌든 구문 적으로 만 적용됩니다. const
비- 일부 필드가 const
struct
실제로 읽기 전용 스토리지에 배치 될 방법은 없습니다 . 그러나 표준에 대한 이러한 표현은 const
이러한 필드의 접근 자 절차에서 필드 의 한정자 를 의도적으로 쫓아내는 코드를 불법화합니다 ( 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);
}
따라서 어떤 이유로 전체 struct
를 읽기 전용으로 선언하면 충분합니다.const
const S_t s3;
그러나 전체 struct
가 읽기 전용이 아닌 경우 w / o로 선언하는 것만으로는 충분하지 않습니다 const
.
내가 더 좋을 것이라고 생각하는 것은 다음 중 하나입니다.
- 필드를 사용 하여 비
const
구조체 생성을 제한하고const
그러한 경우 진단을 발행합니다. 그것은struct
포함하는 읽기 전용 필드가 읽기 전용 이라는 것을 분명히 합니다. - 위의 코드 (*) 가 표준을 준수하도록
const
비const
구조에 속하는 필드에 쓸 경우 동작을 정의합니다 .
그렇지 않으면 행동이 일관되고 이해하기 어렵습니다.
그렇다면 C Standard가 const
재귀 적 으로 재점 을 고려하는 이유는 무엇 입니까?