const type qualifier
Каждый отдельный тип в
системе типов
C имеет несколько
квалифицированных
версий этого типа, соответствующих одному, двум или всем трём квалификаторам:
const
,
volatile
, и, для указателей на объектные типы,
restrict
. На этой странице описываются эффекты квалификатора
const
.
Объекты объявленные с квалификатором const могут быть размещены компилятором в памяти только для чтения, и если адрес константного объекта никогда не используется в программе, он может вообще не храниться.
Любая попытка изменить объект, тип которого квалифицирован как const, приводит к неопределённому поведению.
const int n = 1; // объект типа с квалификатором const int* p = (int*)&n; *p = 2; // неопределённое поведение
const
семантика применяется только к
lvalue-выражениям
; всякий раз, когда константное lvalue-выражение используется в контексте, не требующем lvalue, его квалификатор
const
теряется (обратите внимание, что квалификатор volatile, если присутствует, не теряется).
Выражения lvalue, которые обозначают объекты типа с квалификатором const, и выражения lvalue, которые обозначают объекты структурного или объединенного типа с хотя бы одним членом с квалификатором const (включая члены рекурсивно содержащихся агрегатов или объединений), не являются modifiable lvalues . В частности, они не могут быть присвоены:
const int n = 1; // объект константного типа n = 2; // ошибка: тип n квалифицирован как const int x = 2; // объект неквалифицированного типа const int* p = &x; *p = 3; // ошибка: тип lvalue *p квалифицирован как const struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2}; s1 = s2; // ошибка: тип s1 неквалифицирован, но содержит константный член
Член структуры или объединения с квалификатором const приобретает квалификацию типа, к которому он принадлежит (как при доступе с помощью оператора
.
, так и оператора
->
).
struct s { int i; const int ci; } s; // тип s.i - int, тип s.ci - const int const struct s cs; // типы cs.i и cs.ci оба являются const int
|
Если тип массива объявлен с квалификатором типа const (с использованием typedef ), тип массива не квалифицирован как const, но его тип элемента является таковым. |
(until C23) |
|
Тип массива и его тип элемента всегда считаются идентично квалифицированными как const. |
(since C23) |
typedef int A[2][3]; const A a = {{4, 5, 6}, {7, 8, 9}}; // массив массивов константных int int* pi = a[0]; // Ошибка: a[0] имеет тип const int* void *unqual_ptr = a; // OK до C23; ошибка начиная с C23 // Примечание: clang применяет правило из C++/C23 даже в режимах C89-C17
Если тип функции объявлен с квалификатором типа const (с использованием typedef ), поведение не определено.
|
В объявлении функции ключевое слово
Следующие два объявления объявляют одну и ту же функцию: void f(double x[const], const double y[const]); void f(double * const x, const double * const y); |
(начиная с C99) |
|
Константно-квалифицированные составные литералы не обязательно обозначают различные объекты; они могут использовать общую память с другими составными литералами и со строковыми литералами, которые случайно имеют одинаковое или перекрывающееся представление. const int* p1 = (const int[]){1, 2, 3}; const int* p2 = (const int[]){2, 3, 4}; // the value of p2 may equal p1+1 _Bool b = "foobar" + 3 == (const char[]){"bar"}; // the value of b may be 1 |
(начиная с C99) |
Указатель на неконстантный тип может быть неявно преобразован в указатель на константную версию того же или совместимого типа. Обратное преобразование требует явного приведения типа.
int* p = 0; const int* cp = p; // OK: добавляет квалификаторы (int к const int) p = cp; // Ошибка: отбрасывает квалификаторы (const int к int) p = (int*)cp; // OK: приведение типа
Обратите внимание, что указатель на указатель на
T
не конвертируется в указатель на указатель на
const T
; для совместимости двух типов их квалификаторы должны быть идентичны.
char *p = 0; const char **cpp = &p; // Ошибка: char* и const char* несовместимые типы char * const *pcp = &p; // OK, добавляет квалификаторы (char* в char*const)
Содержание |
Ключевые слова
Примечания
C перенял квалификатор const из C++, но в отличие от C++, выражения типа с квалификатором const в C не являются константными выражениями ; они не могут использоваться в качестве меток case или для инициализации объектов статической и потоковой длительности хранения, перечислителей или размеров битовых полей . При использовании в качестве размеров массивов , результирующие массивы являются VLA.
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 6.7.3 Квалификаторы типа (стр. 87-90)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 6.7.3 Квалификаторы типа (стр: 121-123)
- Стандарт C99 (ISO/IEC 9899:1999):
-
- 6.7.3 Квалификаторы типа (стр: 108-110)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
-
- 6.5.3 Квалификаторы типа
Смотрите также
|
C++ documentation
для
cv (
const
и
volatile
) квалификаторов типа
|