C99 standardı 6.5.16: 2'de diyor:
Bir atama operatörü, sol işlenen olarak değiştirilebilir bir değere sahip olacaktır.
ve 6.3.2.1:1'de:
Değiştirilebilir bir değer, dizi türüne sahip olmayan, tamamlanmamış bir türe sahip olmayan, sabit nitelikli bir türe sahip olmayan ve bir yapı veya birleşim olan herhangi bir üyesi olmayan (yinelemeli olarak herhangi bir üye dahil) bir değerdir. veya içerilen tüm agregaların veya birliklerin elemanı).
Şimdi, alan olmayan const
struct
bir const
alanı ele alalım .
typedef struct S_s {
const int _a;
} S_t;
Standart olarak, aşağıdaki kod tanımsız davranıştır (UB):
S_t s1;
S_t s2 = { ._a = 2 };
s1 = s2;
Bununla ilgili anlamsal sorun, ekteki varlık ( struct
) 'ın beyan edilen kuruluş türü ( ) ile değerlendirilerek yazılabilir (salt okunur olmayan S_t s1
) olarak kabul edilmesi, ancak standardın (2 fıkraları ile yazılabilir olarak kabul edilmemesi) üstte) const
alan nedeniyle _a
. Standart, bir programcının atamanın gerçekte bir UB olduğunu kodunu okumasını netleştirmez, çünkü struct S_s ... S_t
tür tanımının w / o olduğunu söylemek imkansızdır .
Dahası, alana salt okunur erişim sadece sözdizimsel olarak zorunlu kılınmıştır. Bazı const
non-non alanlarının const
struct
salt okunur depolamaya yerleştirilmesinin hiçbir yolu yoktur . Ancak bu tür standart ifadeler, const
bu alanların erişimci prosedürlerindeki alanların niteleyicisini kasıtlı olarak ortadan kaldıran kodu , bu şekilde ( C'deki yapı alanlarını daraltmak iyi bir fikir mi? ):
(*)
#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);
}
Bu nedenle, bir nedenden dolayı, bir bütünün struct
salt okunur olması için bunu beyan etmek yeterlidirconst
const S_t s3;
Ancak bir bütünün struct
salt okunur olmaması için, bunu w / o olarak bildirmek yeterli değildir const
.
Ne daha iyi olacağını düşünüyorum, ya da:
const
Yapı olmayan yapıların oluşturulmasınıconst
alanlarla sınırlamak ve böyle bir durumda teşhis koymak. Bu,struct
içerdiği salt okunur alanların salt okunur olduğunu açıkça ortaya koyacaktır.- Yapıya
const
ait olmayan bir alana yazma durumunda davranışı,const
yukarıdaki kodu (*) Standart ile uyumlu hale getirecek şekilde tanımlamak .
Aksi takdirde davranış tutarlı ve anlaşılması zor değildir.
Öyleyse, C Standardının, const
-sayıya koyduğu gibi, özyineliği tekrar tekrar düşünmesinin nedeni nedir?