Namespaces
Variants

const type qualifier

From cppreference.net

Каждый отдельный тип в системе типов 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 ), поведение не определено.

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

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

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)

Содержание

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

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 ) квалификаторов типа