Эта статья является продолжением предыдущей статьи « Операторы на C» , где мы начали с Postfix Operators и обсудили оператор индекса Array и оператор вызова функции. Продолжая операторы постфикса, третий оператор — это оператор точки (.) И оператор стрелки (->) , используемый для доступа к элементам структуры и объединения.
3. Структура и члены Союза
Структура — это определяемый пользователем тип данных, который представляет собой набор упорядоченной группы объектов данных. В отличие от элементов массива, объекты данных в структуре имеют разные типы данных. Каждый объект данных в структуре / объединении называется членом структуры / объединения.
Объединение также является определяемым пользователем типом, который представляет собой набор объектов данных, имеющих разные типы данных. Однако, в отличие от структуры, члены объединения имеют одну и ту же область хранения, хотя отдельные члены могут различаться по типу. Таким образом, объединение позволяет хранить несколько разных элементов данных в одной и той же части памяти компьютера в разное время.
например:
struct student { int student_id; char [] student_name; };
Приведенное выше объявление структуры создает определенный пользователем тип данных с именем student
. Структура student состоит из двух членов: student_id
и student_name.
Чтобы получить доступ к членам структуры, нам нужно сначала объявить переменную определяемого пользователем типа данных student
, а затем мы будем использовать оператор точки (.)
Для доступа к отдельным членам структуры.
структура студент студент1;
Вышеупомянутое утверждение создает структурную переменную student1
типа student
. Теперь для доступа к каждому члену структуры мы будем использовать оператор точки.
Точка Оператор
Синтаксис:
structurevariable.membername;
пример:
student1.student_id = 101; student1.student_name = "Алиса";
Вышеуказанные два оператора обращаются к отдельным членам структуры и присваивают им значения.
Доступ к объединению также осуществляется аналогичным образом с помощью оператора точки. Союз объявляется следующим образом:
название объединения {
datatype1 member1;
datatype2 member2;
,
,
,
тип данныхN memberN;
};
Синтаксис для объявления переменной объединения:
переменная unionname;
Чтобы получить доступ к члену профсоюза:
variable.member
Стрелка Оператор
Начальный адрес переменной структуры / объединения может быть сохранен в переменной указателя, а затем к отдельным членам структуры / объединения можно получить доступ с помощью переменной указателя и оператора Arrow ->.
Например:
структура студент студент1;
структура студента * Stud1;
объявляет указатель на структуру student
. Чтобы сохранить начальный адрес структурной переменной student1
в переменной-указателе *stud1
мы будем использовать адрес оператора &
.
* Stud1 = & student1;
Теперь для доступа к отдельным членам мы можем использовать указатель *stud1
и оператор стрелки следующим образом:
stud1-> student_id;
stud1-> student_name;
Оператор стрелки используется аналогичным образом в случае объединения. Оператор точки и оператор стрелки будут обсуждены более подробно, когда мы обсудим структуры и объединения в следующей статье.
4. Постфиксные операторы инкремента и декремента
Операторы постфиксного приращения и постфиксного декремента работают только с одним операндом, который может быть либо переменной-указателем, либо переменной, принадлежащей к реальным типам данных: целочисленным типам и типам с плавающей запятой ( int, float, double
вместе с модификаторами различных типов) ,
Операция увеличения постфикса (операнд ++) увеличивает значение переменной на 1, а операция уменьшения постфикса (операнд -) уменьшает значение переменной на 1.
Постфиксное выражение в форме E ++, где E — переменная, эквивалентно E = E + 1. Аналогично, постфиксное выражение вида E– эквивалентно E = E-1.
Следовательно ,
int i = 10; я ++;
Е ( "% d", я); // печатает 11 я--;
Е ( "% d", я); // печатает 10
Результат операции увеличения или уменьшения постфикса отличается в сочетании с оператором присваивания (=). В операции увеличения / уменьшения постфикса предыдущее значение переменной, которая увеличивается / уменьшается, сначала присваивается переменной, содержащей результат операции увеличения / уменьшения постфикса, а затем выполняется операция увеличения / уменьшения; то есть сначала происходит присвоение, а затем увеличение / уменьшение . Чтобы понять это, рассмотрим следующий пример:
#include <stdio.h> int main () { int a, i = 10; а = я ++; printf («a =% d, i =% d», a, i); а = i--; printf («a =% d, i =% d», a, i); вернуть 0; }
Выход:
а = 10, я = 11
а = 11, I = 10
Это связано с тем, что в операции постфиксного увеличения / уменьшения значение i сначала присваивается, а затем обновляется.
Поэтому в первом утверждении a=i++;
Сначала присваивается предыдущее значение i
равное 10, а затем обновляется до 11.
Во втором утверждении a=i--;
a
снова присваивается предыдущее значение i
(i = 11 сейчас, из-за предыдущей операции приращения), а затем i
уменьшается до 10.
5. Составные литералы
Постфиксное выражение, состоящее из имени типа данных в скобках, за которым следует заключенный в скобки список инициализаторов, называется составным литералом. Тип данных может быть либо полным типом (целочисленные типы со знаком, со знаком и без знака, типы с плавающей запятой и тип указателя), либо массивом неизвестного размера, но не массивом переменной длины (мы обсудим массивы переменной длины позже. статья о массивах).
Составной литерал инициализирует неназванный объект. Если имя типа данных указывает массив неизвестного размера, размер определяется количеством элементов в списке инициализатора.
Некоторые примеры составных литералов:
Массив неизвестного размера
(int []) {2,4,7,6};
Вышеупомянутый составной литерал является массивом целочисленного типа неизвестного размера. Размер массива определяется как 4 после завершения инициализации.
Создание объектов структуры с использованием составных литералов
Чтобы создать объект структуры, мы инициализируем каждого члена структуры через отдельные операторы инициализации; такие как
структура студент студент1;
student1.student_id = 101;
student2.student_name = "Алиса";
То же самое можно сделать в более компактной форме, используя составные литералы следующим образом:
(struct student1) { . student_id = 101, , student_name = "Алиса"};
Обратите внимание, что оператор «точка» все еще используется в фигурных скобках.
Указатель на структуру, используемую в качестве составного литерала
Чтобы инициализировать элемент структуры с помощью указателей, мы объявляем указатель на объект структуры, а затем инициализируем каждый элемент в отдельных операторах инициализации с помощью оператора стрелки; как в:
struct student student1, * stud1;
* Stud1 = & student1;
stud1-> student_id = 101;
stud1-> student_name = "Алиса";
Для выполнения той же работы с использованием составных литералов мы не используем оператор стрелки. Скорее, то же самое можно сделать очень компактным способом, используя оператор точки и адрес оператора (&), как показано ниже:
& (struct student1) { . student_id = 101, .student_name = "Алиса"};
Создание константы сложного литерала
Составной литерал только для чтения; то есть константный составной литерал, может быть задан префиксом ключевого слова const:
( const int []) {1,2,3,4,5};
(const char []) {"Температура"};
Кодирование становится намного более компактным, когда используются составные литералы. Есть еще несколько моментов, связанных с составным литералом, таких как передача их функциям, их область действия и т. Д., Которые будут обсуждаться позже, когда мы поймем функции.
Унарные операторы
Унарные операторы работают только с одним операндом. Есть четыре унарных оператора:
1. Префиксные операторы увеличения и уменьшения
2. Адреса и адреса операторов
3. Размеры и выравнивание операторов
4. Унарные арифметические операторы
Операторы приращения и уменьшения префикса
Префиксные операторы увеличения и уменьшения работают только с одним операндом, который может быть либо переменной-указателем, либо переменной, принадлежащей к реальным типам данных: целочисленным типам и типам с плавающей запятой ( int, float, double
вместе с модификаторами различных типов).
Операция увеличения префикса (операнд ++) увеличивает значение на 1, а операция уменьшения префикса (операнд -) уменьшает значение на 1. Постфиксное выражение в форме ++ E, где E — переменная, эквивалентно E = E + 1. Аналогично, постфиксное выражение вида –E эквивалентно E = E-1.
Было видно, что в случае постфикса сначала происходит приращение / уменьшение, а затем приращение / уменьшение. Однако в случае операции увеличения или уменьшения префикса предыдущее значение сначала увеличивается / уменьшается, а затем происходит присвоение.
Чтобы понять это, рассмотрим следующий фрагмент кода.
#include <stdio.h> int main () { int i = 10, a; ++ I; printf ("Значение i =% d", i); // печатает 11 --я; printf ("Значение i =% d", i); // печатает 10 а = ++ я; printf ("Значение a =% d", a); // печатает 11 printf ("Значение i =% d", i); // печатает 11 а = - я; printf ("Значение a =% d", a); // печатает 10 printf ("Значение i =% d", i); // печатает 10 вернуть 0; }
Здесь мы видим, что значение i было сначала обновлено, а затем присвоено. Следовательно, a содержит обновленное значение i, а не предыдущее значение, как в случае с постфиксным увеличением / уменьшением.
Адреса и операторы переадресации
Адрес оператора & используется для оценки адреса его операнда.
Оператор косвенного обращения * используется для оценки значения, хранящегося по адресу, указанному его операндом. Операнд должен иметь тип указателя; т. е. это может быть либо массив (который является самоссылочным указателем), либо указатель на переменную (указатель данных), либо указатель на функцию (указатель на функцию).
Пример указателя данных:
#include <stdio.h> int main () { int val, a = 10; int * p; // объявляем переменную указателя р = & а; // теперь p хранит адрес Val = * р; // теперь val хранит значение printf («Адрес a:% X», p); printf («Значение a:% d», val); вернуть 0; }
В вышеприведенной программе оператор int *p
объявляет целочисленный указатель (указатель, в котором хранится адрес целочисленной переменной).
Для сохранения адреса a в p адрес оператора применяется к a, а результат сохраняется в p, как показано в инструкции p=&a;
Теперь p=&a;
Предположим, что адрес a равен 1004, т.е. &a=1004
Поскольку p хранит адрес a, то p=&a
p = 1004
Теперь значение, присутствующее по адресу 1004, является значением, хранящимся в a, которое равно 10 (a = 10).
Чтобы получить доступ к значению, хранящемуся в переменной-указателе p
нам нужно применить оператор косвенности *
к p
. Когда оператор косвенности применяется к p (*p)
, он считывает значение, хранящееся по адресу, указанному в p;
т.е. значение хранится по адресу 1004; значение a
. Результат косвенного действия сохраняется в переменной целочисленного типа val
как показано в инструкции val =*p
; Оператор косвенного обращения также называется значением в операторе, поскольку он дает значение, хранящееся по определенному адресу.
Чтобы прочитать адрес, сохраненный в p, в выражении printf
используется printf
формата %X
как адреса обычно в шестнадцатеричном формате.
Связь между указателями и массивами обсуждалась до некоторой степени при обсуждении оператора индекса массива. Указатели на функции — это продвинутая концепция, которая будет обсуждаться в следующей статье об указателях.
Следующая статья будет продолжена с унарными операторами и другими операторами в C.