КАТЕГОРИИ:
АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника
|
Операции С, их приоритеты и использование. Преобразование типовЦель работы: Изучить основные логические, арифметические и другие операции С,научиться правильно составлять выражения С, изучить приоритеты операций С, научиться использовать преобразование типов. Теоретические сведения Язык С имеет мощную арифметическую и логическую основу, которая позволяет быстро, компактно и эффективно писать код программы. В С разработано множество базовых арифметических и логических операций, а также функции библиотеки математической поддержки языка. Операндами операций могут быть выражения определённых видов, зависящих от операции. В простейшем случае операндами являются переменные. Переменные, прежде чем они будут использованы, должны быть объявлены с определённым спецификатором типа. Таблица 19 - допустимые операции над переменными
Приоритет операций и порядок выполнения (ассоциативность) Приоритет и ассоциативность операций влияют на порядок группирования операндов и порядок вычислений в выражениях С. Например, приоритет выполнения операций необходимо учитывать при составлении сложных арифметических формул. Операции, приведенные в одной группе таблицы, имеют одинаковый приоритет и ассоциативность. Порядок убывания приоритета сверху вниз. Таблица 20 - Приоритет операций
Если несколько операций одного приоритета встречаются в выражении, то они применяются в соответствии с ассоциативностью. Примеры. а = b&ÆхFF + 5; // вычисляется как а = b&(Æх FF + 5); b=а + с >> 1; // как b=(а +с) >> 1; с = а + + + b/5; //какс=(а + +) + ( b/5); Мультипликативные, аддитивные и поразрядные операции обладают свойством коммутативности. Компилятор вычисляет выражения с учётом приоритета в любом порядке, даже если есть скобки. Определённый порядок вычисления (,) операндов гарантируют операции: последовательного вычисления, логические «И» (&&)и «ИЛИ» (||), условная операция(? :). Запятые в вызовах функций не являются операциями последовательного вычисления и не обеспечивают гарантий вычисления слева направо. Логические операции вычисляют минимальное число операндов, необходимых для определения результатов выражения. func (i + 1, i = j + 2); //. Не гарантирует порядок вычисления фактических // аргументов i= 0;// iимеет тип int по умолчанию a [++ i] = i; // порядок вычисления левого и правого операндов не (x - 5) && ++ i // Если x =5, то ++ i не вычисляется int x, y, z, f(); z = x > y || f(x, y); // Если x > y,то значение z = 1 «Истина», а f( ) –не // вызывается // если x £ y, то f() вызывается, тогда z=0, // eсли f( ) возвращает нулевое значение, или z = 1, // если f( ) возвращает не нулевое значение // printf (“%d %d \n“, ++n, p()2, n) //в функцию может передаваться n или n+1.
Преобразование типов В выражениях С переменные различных типов в ряде случаев могут использоваться совместно; например, переменные типа char могут присутствовать в выражениях одновременно с переменными типа int. Пример совместного использования целых и символьных переменных. char ch='a', ans; //объявление переменныхchиans printf("значение ch + 3 = %d", ch+3); //вывод значенияch+3 ans = ch % 3;// определение остатка от целочисленного деления printf("\n\n значение ans = % d\n", ans); Поскольку char это целый тип, для него применимы все операции, операнды которых могут иметь тип int. Целые по умолчанию - это величины со знаком signed. С переменными вещественного типа (float, double и др.) применимы все операции, допустимые для целого типаint,за исключением операции остатка от деления (%). Преобразования типов бывают явные и неявные. Синтаксис операции явного преобразования типа (<новый_тип>) <операнд> или <новый_тип> (<операнд>). Ряд операций может в зависимости от типов своих операндов вызывать неявное преобразование значения операнда из одного типа в другой (преобразование по умолчанию). Рассмотрим результаты таких преобразований. Данные типа charили short intмогут использоваться везде, где используется тип int. Во всех случаях значение преобразуется к целому типу Арифметические операции над числами с плавающей точкой (floatиdouble) по умолчанию выполняются с двойной точностью. Преобразования целочисленных значений в вещественные (плавающие) выполняется без осложнений, но возможна потеря точности, если для результата не предусмотрено достаточного количества битов. Преобразование значений с плавающей точкой к целочисленному типу машинно-зависимо. Результат неопределен, если значение не попадает в отведенный диапазон. Если целое без знака (unsigned)используется вместе с простым целым, то простое целое и результат преобразуются в целое без знака. Подавляющее большинство операций вызывает преобразование и определяет типы результата в соответствии с вышеприведенными правилами. Приведенная ниже схема преобразований реализуется по умолчанию при вычислении выражений С. Сначала любые операнды типов char, unsigned char или short преобразуются в int, а любые операнды типа float преобразуются в double. Затем, если какой-либо операнд имеет тип double, то другой преобразуется к типу double и типом результата будет double. В случае, если какой-либо операнд имеет тип unsigned long, то другой преобразуется к типу unsigned long и это же будет и типом результата. В случае, если какой-либо операнд имеет тип long, то другой преобразуется к типу long и это же будет типом результата. В случае, если операнд имеет тип unsigned, то другой операнд преобразуется к типу unsigned, и это будет типом результата. Объект типа void* (указатель на пустой)может быть объявлен для указания на объекты неизвестного типа. Преобразование типа такого указателя задаётся с помощью явной операции преобразования типов. Указатель может преобразовываться в любой из целых типов, достаточно большой для того, чтобы вместить его. Указатель на один тип может быть преобразован в указатель на другой тип. При этом возможно преобразование указателя в указатель на объект меньшего размера и обратно без изменений. Например, функция выделения памяти может принимать размер (в байтах) объекта, для которого выделяется память, и возвращать указателю несоответствующий тип, который может таким образом использоваться. extern void* allos (); doube* dp; dp = (doube*) allos (sizeof (doube)); *dp = 2,6/8,4
|