Операторы присваивания
Операторы присваивания и составного присваивания являются бинарными операторами, которые изменяют переменную слева, используя значение справа.
| Оператор | Название оператора | Пример | Описание | Эквивалент |
|---|---|---|---|---|
= | основное присваивание | a = b | a становится равным b | Н/Д |
+= | присваивание с сложением | a += b | a становится равным сумме a и b | a = a + b |
-= | присваивание с вычитанием | a -= b | a становится равным результату вычитания b из a | a = a - b |
*= | присваивание с умножением | a *= b | a становится равным произведению a и b | a = a * b |
/= | присваивание с делением | a /= b | a становится равным результату деления a на b | a = a / b |
%= | присваивание по модулю | a %= b | a становится равным остатку от деления a на b | a = a % b |
&= | побитовое присваивание И | a &= b | a становится равным результату побитового И a и b | a = a & b |
|= | побитовое присваивание ИЛИ | a |= b | a становится равным результату побитового ИЛИ a и b | a = a | b |
^= | побитовое присваивание XOR | a ^= b | a становится равным результату побитового XOR a и b | a = a ^ b |
<<= | побитовое присваивание сдвиг влево | a <<= b | a становится равным результату сдвига a влево на b | a = a << b |
>>= | побитовое присваивание сдвиг вправо | a >>= b | a становится равным результату сдвига a вправо на b | a = a >> b |
Простое присваивание
Выражения с оператором простого присваивания имеют вид
lhs = rhs |
где
| lhs | - | выражение типа изменяемая lvalue любого полного типа объекта |
| rhs | - | выражение любого типа, неявным образом приводимого к lhs или совместимого с lhs |
Присваивание выполняет неявное преобразование значения rhs к типу lhs, а затем заменяет значение в объекте, обозначенном lhs, преобразованным значением rhs.
Присваивание также возвращает то же значение, что и хранилось в lhs (чтобы были возможны выражения, такие как a = b = c). Категория значений оператора присваивания - не-lvalue (так что выражения, такие как (a=b)=c недействительны).
rhs и lhs должны удовлетворять одному из следующих условий:
- оба lhs и rhs имеют совместимый тип структуры или объединения, или..
- rhs должен быть неявным образом преобразуемым к lhs, что подразумевает
- оба lhs и rhs имеют арифметические типы, в этом случае lhs может быть volatile-квалифицированным или атомным(с C11)
- оба lhs и rhs имеют указатель на совместимые (без учета квалификаторов) типы, или один из указателей является указателем на void, и преобразование не добавит квалификаторов к типу, на который указывает указатель. lhs может быть volatile или restrict(с C99)-квалифицированным или атомным(с C11).
- lhs является (возможно, квалифицированным или атомным(с C11)) указателем, а rhs является константой нулевого указателя, например
NULLили значениемnullptr_t(с C23)
| (с C99) |
| (с C23) |
Примечания
Если rhs и lhs перекрываются в памяти (например, являются членами одной и той же объединения), поведение не определено, если перекрытие не является точным и типы не совместимы.
Хотя массивы не присваиваются, массив, заключённый в структуру, можно присвоить другому объекту того же (или совместимого) типа структуры.
Побочный эффект обновления lhs определён после вычисления значений, но не побочных эффектов lhs и rhs самих по себе, и вычисления операндов, как обычно, не упорядочены относительно друг друга (поэтому выражения, такие как i=++i; неопределены).
Присваивание удаляет дополнительные диапазон и точность из выражений с плавающей запятой (см. FLT_EVAL_METHOD).
В C++, операторы присваивания являются выражениями lvalue, а не в C.
#include <stdio.h>
int main(void)
{
// integers
int i = 1, j = 2, k = 3; // initialization, not assignment
i = j = k; // values of i and j are now 3
// (i = j) = k; // Error: lvalue required
printf("%d %d %d\n", i, j, k);
// pointers
const char c = 'A'; // initialization; not assignment
const char *p = &c; // initialization; not assignment
const char **cpp = &p; // initialization; not assignment
// cpp = &p; // Error: char** is not convertible to const char**
*cpp = &c; // OK, char* is convertible to const char*
printf("%c \n", **cpp);
cpp = 0; // OK, null pointer constant is convertible to any pointer
// arrays
int arr1[2] = {1,2}, arr2[2] = {3, 4};
// arr1 = arr2; // Error: cannot assign to an array
printf("arr1[0]=%d arr1[1]=%d arr2[0]=%d arr2[1]=%d\n",
arr1[0], arr1[1], arr2[0], arr2[1]);
struct { int arr[2]; } sam1 = { {5, 6} }, sam2 = { {7, 8} };
sam1 = sam2; // OK: can assign arrays wrapped in structs
printf("%d %d \n", sam1.arr[0], sam1.arr[1]);
}Вывод:
3 3 3 A arr1[0]=1 arr1[1]=2 arr2[0]=3 arr2[1]=4 7 8
Составное присваивание
Выражения с операторами составного присваивания имеют вид
| lhs op rhs |
где
| op | - | один из *=, /= %=, += -=, <<=, >>=, &=, ^=, |= |
| lhs, rhs | - | выражения с арифметическими типами (где lhs может быть квалифицированным или атомным), за исключением случаев, когда op является += или -=, которые также принимают типы указателей с теми же ограничениями, что и + и - |
Выражение lhs @= rhs точно такое же, как lhs = lhs @ ( rhs ), за исключением того, что lhs оценивается только один раз.
| Если lhs имеет атомный тип, операция ведет себя как единая атомная операция чтения-модификации-записи с порядком памяти Для целочисленных атомных типов составное присваивание T1* addr = &lhs;
T2 val = rhs;
T1 old = *addr;
T1 new;
do { new = old @ val } while (!atomic_compare_exchange_strong(addr, &old, new); | (с C11) |
#include <stdio.h>
int main(void)
{
int x = 10;
int hundred = 100;
int ten = 10;
int fifty = 50;
printf("%d %d %d %d\n", x, hundred, ten, fifty);
hundred *= x;
ten /= x;
fifty %= x;
printf("%d %d %d %d\n", x, hundred, ten, fifty);
return 0;
}Вывод:
10 100 10 50 10 1000 1 0
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
- 6.5.16 Операторы присваивания (с. 72-73)
- Стандарт C11 (ISO/IEC 9899:2011):
- 6.5.16 Операторы присваивания (с. 101-104)
- Стандарт C99 (ISO/IEC 9899:1999):
- 6.5.16 Операторы присваивания (с. 91-93)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
- 3.3.16 Операторы присваивания
См. также
| Общие операторы | ||||||
|---|---|---|---|---|---|---|
| присваивания | инкремента декремента | арифметические | логические | сравнения | доступа к членам объекта | прочие |
|
|
|
|
|
|
|
|
См. также
| Документация C++ по Операторам присваивания |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/operator_assignment