Spec-Zone.ru › C

Квалификатор типа const

Каждый отдельный тип в системе типов C тип имеет несколько квалифицированных версий этого типа, соответствующих одному, двум или всем трём из const, volatile и, для указателей на типы объектов, restrict квалификаторов. На этой странице описываются эффекты квалификатора const.

Объекты, объявленные с квалифицированным типом const, могут быть помещены в память только для чтения компилятором, и если адрес объекта const никогда не берётся в программе, то он может вообще не храниться.

Любая попытка изменить объект, тип которого квалифицирован как const, приводит к неопределённому поведению.

const int n = 1; // object of const-qualified type
int* p = (int*)&n;
*p = 2; // undefined behavior

Семантика const применяется только к выражениям lvalue; всякий раз, когда выражение const lvalue используется в контексте, не требующем lvalue, его квалификатор const теряется (обратите внимание, что квалификатор volatile, если он присутствует, не теряется).

Выражения lvalue, которые обозначают объекты с квалификацией const, и выражения lvalue, которые обозначают объекты типа struct или union с хотя бы одним членом с квалификацией const (включая члены рекурсивно содержащихся агрегатов или объединений), не являются изменяемыми lvalue. В частности, они не могут быть присвоены:

const int n = 1; // object of const type
n = 2; // error: the type of n is const-qualified
 
int x = 2; // object of unqualified type
const int* p = &x;
*p = 3; // error: the type of the lvalue *p is const-qualified
 
struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2};
s1 = s2; // error: the type of s1 is unqualified, but it has a const member

Член квалифицированного типом const структуры или объединения приобретает квалификацию типа, к которому он принадлежит (как при обращении с помощью оператора . или оператора ->).

struct s { int i; const int ci; } s;
// the type of s.i is int, the type of s.ci is const int
const struct s cs;
// the types of cs.i and cs.ci are both const int

Если тип массива объявлен с квалификатором типа const (через использование typedef), тип массива не квалифицирован как const, но его элементный тип является квалифицированным.

(до C23)

Тип массива и его элементный тип всегда считаются идентично квалифицированными как const.

(с C23)
typedef int A[2][3];
const A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of const int
int* pi = a[0]; // Error: a[0] has type const int*
void *unqual_ptr = a; // OK until C23; error since C23
// Notes: clang applies the rule in C++/C23 even in C89-C17 modes

Если тип функции объявлен с квалификатором типа const (через использование typedef), поведение является неопределённым.

В объявлении функции ключевое слово const может появляться внутри квадратных скобок, используемых для объявления типа массива параметра функции. Оно квалифицирует тип указателя, в который преобразуется тип массива.

Следующие два объявления объявляют одну и ту же функцию:

void f(double x[const], const double y[const]);
void f(double * const x, const double * const y);
(с C99)

Квалифицированные const составные литералы необязательно обозначают отдельные объекты; они могут совместно использовать память с другими составными литералами и со строковыми литералами, которые имеют одинаковое или перекрывающееся представление.

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)

Указатель на тип, не являющийся const, может быть неявным образом преобразован в указатель на квалифицированный версию const того же или совместимого типа. Обратное преобразование требует выражения приведения типа.

int* p = 0;
const int* cp = p; // OK: adds qualifiers (int to const int)
p = cp; // Error: discards qualifiers (const int to int)
p = (int*)cp; // OK: cast

Обратите внимание, что указатель на указатель на T не может быть преобразован в указатель на указатель на const T; для того чтобы два типа были совместимы, их квалификации должны быть идентичны.

char *p = 0;
const char **cpp = &p; // Error: char* and const char* are not compatible types
char * const *pcp = &p; // OK, adds qualifiers (char* to char*const)

Ключевые слова

const

Примечания

C унаследовал квалификатор const от C++, но в отличие от C++, выражения с квалифицированным типом const в C не являются постоянными выражениями; они не могут использоваться в качестве меток case или для инициализации объектов со статическим и потоковым сроком жизни, перечислителей или размеров битовых полей. Когда они используются в качестве размеров массивов, получающиеся массивы являются массивами переменной длины.

Ссылки

  • Стандарт 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++ для квалификаторов типов cv (const и volatile)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/const

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API