Продолжая мою последнюю статью об основах C , мы теперь рассмотрим операторы.
Выражение — это последовательность операторов и операндов, которая вычисляет значение. Оператор в C — это символ, который приказывает компьютеру выполнять математические или логические манипуляции с данными. Элементы данных, на которые действуют операторы, называются операндами.
Различные операторы, поддерживаемые C:
1. Постфиксные операторы
2. Унарные операторы
3. Операторы броска
4. Мультипликативные операторы
5. Аддитивные операторы
6. Битовые операторы сдвига
7. Операторы отношений
8. Операторы равенства
9. И оператор
10.Отключающий оператор ИЛИ
11. Вкл. ИЛИ Оператор
12. Логика И Оператор
13. Логический оператор ИЛИ
14. Условный оператор
15. Назначение операторов
16. Операторы запятой
Постфиксные операторы
Оператор называется постфиксным оператором, когда оператор следует за операндом. Операторы Postfix могут работать с одним или двумя операторами. В C есть пять постфиксных операторов:
1. Массив подписок
2. Функциональный вызов
3. Структура и члены Союза
4. Постфиксные операторы инкремента и декремента
5. Составные литералы
1. Массив подписок
Мы уже определили массивы в предыдущей статье как идентификатор, который ссылается на набор элементов данных, имеющих одинаковое имя и одинаковый тип данных. Каждый элемент данных представлен своим элементом массива. Отдельные элементы массива отличаются друг от друга своими индексами.
Постфиксное выражение (операнд, за которым следует оператор), за которым следует выражение в квадратных скобках [], является подписанным обозначением элемента массива. Определение оператора индекса массива [] состоит в том, что если a является массивом, а i является целым числом, то a[i] =*(a+i)
Если оператор индексации массива [] применяется к n-мерному массиву x с размерами n> = 2, то x
Доступ к отдельным элементам массива осуществляется с помощью оператора косвенности *.
Чтобы понять приведенное выше определение, необходимо понять концепцию указателей и связь между массивами и указателями.
Имя массива всегда хранит адрес первого элемента массива. Например, если x[10]
x
x[0]
Поскольку x
Поэтому к каждому элементу массива можно получить доступ с точки зрения смещения, добавленного к адресу первого элемента. Здесь смещение — это индекс * памяти, занимаемый типом данных массива. Поэтому второй элемент x[1]
x[2]
Указатель — это переменная, в которой хранится адрес другой переменной. В этих терминах массив упоминается как самоссылочный указатель, поскольку он хранит свой собственный адрес, то есть адрес первого элемента. Поэтому каждый элемент массива может быть представлен в виде указателя (имя массива) и смещения (нижний индекс). Таким образом, x[1]
x+1
x[2]
x+2
Значение нижнего индекса определяет, сколько раз требования к памяти должны быть добавлены к начальному адресу, чтобы получить местоположение подписанного элемента. Это означает, что для целочисленного массива x
x[2]
Точно так же адрес x[3]
Чтобы найти фактическое значение элемента массива, нужно использовать оператор косвенности * . Следовательно, если x+2
*(x+2)
Если одномерный массив может быть представлен в виде указателя (имя массива) и смещения (нижний индекс), многомерные массивы также могут быть представлены в аналогичных терминах. Следовательно, двумерный целочисленный массив x[2][3]
Этот двумерный массив может быть определен как указатель на группу одномерных массивов, где *x
*(x+1)
Поскольку каждая строка является одномерным массивом, *(x)
*(x+1)
В случае многомерных массивов с более чем двумя измерениями *(x)
*(x+1)
Скорее они будут хранить начальный адрес многомерных массивов. Подробнее об этом, когда мы обсудим массивы и указатели более подробно в следующей статье.
В массиве x[i][j]
x[i]
*(x+i)
j
*(x+1)
Теперь значение i
Требования к памяти здесь — это размер массива элементов j
Рассматривая наш пример x[2][3]
Если *x
*(x+1)
Таким образом, отсюда следует, что многомерные массивы хранятся в главном порядке строк.
Например: пусть x[2][3]= {{5,6,8}, {2,4,7}}
затем * x
*(x+1)
Теперь каждая строка будет занимать 6 байтов, поэтому, если начальный адрес *x
тогда адрес второго ряда — 1182 + 6 = 1188; то есть * (х + 1) = 1188
Теперь для доступа к отдельным элементам применяется оператор косвенности, например: второй элемент первой строки будет расположен по адресу (*(x+0)+1)
*(x+0)
*(x+0)[0]= x[0][0]=5
поскольку нижний индекс дает смещение, тогда *(x+0)[0]= *(*(x+0)+0)=x[0][0]=5
Следовательно, *(*(x+0)+0)
Аналогично, x[0][1] =*(*(x+0)+1*2bytes))=6
Массив и указатель во многом эквивалентны. Здесь мы рассмотрим основные понятия массивов и указателей, чтобы понять оператор индекса массива. Оператор индекса массива станет полностью понятным, как только мы обсудим массивы, а затем подробно рассмотрим указатели.
2. Функциональные вызовы
В моем предыдущем посте « Введение в C» я привел пример функции и представил концепцию прототипа функции, заголовок функции, тип возвращаемого значения и аргументы. Было бы полезно вспомнить эти понятия, чтобы понять оператор вызова функции () .
Выражение postfix, за которым следуют скобки, содержащие аргументы, разделенные запятыми или не содержащие аргументов, называется вызовом функции. Постфиксное выражение обозначает вызываемую функцию.
Тип возвращаемого значения функции может быть функцией, указателем или любым из типов данных, обсужденных ранее. Если возвращаемый тип функции — указатель, то функция возвращает адрес.
Аргумент функции — это выражение, которое используется в скобках вызова функции. Параметр функции — это объект, объявленный в скобках объявления или определения функции. Когда вы вызываете функцию, аргументы оцениваются, и каждый параметр инициализируется значением соответствующего аргумента в том порядке, в котором они присутствуют в вызове функции.
Преобразования типов аргументов
Аргументы, которые являются массивами или функциями, преобразуются в указатели перед передачей в качестве аргументов функции.
Аргументы, передаваемые непрототипированным функциям C, подвергаются преобразованиям: параметры типа char
int
float
double
Это называется продвижением аргументов по умолчанию.
Компилятор сравнивает типы данных, предоставляемые вызывающей функцией, с типами данных, которые вызываемая функция ожидает и выполняет необходимые преобразования типов, поэтому, если вызываемая функция не содержит прототипа, аргументы функции неявно преобразуются в типы параметров функции.
Если у функции нет прототипа, никакие другие типы аргументов неявным образом не преобразуются, кроме упомянутых выше. Число и тип аргументов не сравниваются с параметрами вызываемой функции, если у нее нет декларатора прототипа функции.
Если функция определена с типом возврата, который не совместим с фактическим возвращаемым значением, вы можете получить ошибку или неопределенное поведение программы. Например, char
int
char
float
Если возвращаемый тип функции объявлен как char
Чтобы понять вышеперечисленные моменты, рассмотрим следующий пример:
/ * программа для расчета площади круга с помощью пользовательской функции * / #include <stdio.h> #define PI 3.14159 int main () { площадь плавания, радиус; printf ("n Введите радиус:"); scanf ("% f", & radius); площадь = процесс (радиус); // process (radius) - это вызов функции printf («Площадь =% f», площадь); вернуть 0; } float process (float r) // функция ожидает аргумент float { плавать; / * объявление локальной переменной * / a = PI * r * r; Возвращение (а); // функция возвращает значение. }
Если в вышеприведенной программе отсутствовал прототип функции, и если функция ожидала значение типа double
float
double
Кроме того, если бы функция была объявлена с типом void
Существует гораздо больше понимания работы функций, но мы обсудим их в следующей статье о функциях. Следите за статьей, которая будет опубликована в ближайшее время и которая продолжит изучение операторов в C.