Понятие типа данных. Переменные и константы. Основные типы данных в языке Си: общая характеристика, машин­ное представление, описание данных в программе

Вид материалаЛекция

Содержание


Выраженияю условная операция.
Подобный материал:
ЛЕКЦИЯ 2

Понятие типа данных.Переменные и константы. Основные типы данных в языке Си: общая характеристика, машин­ное представление, описание данных в программе. Чис­ловые, символьные и строковые константы. Арифметичес­кие операции и выражения. Операции отношения, логи­ческие операции и выражения. Условная операция. Автоматическое преобразование типов и операция приведения. Простейшие операторы языка Си. Составной оператор.

$ 1. ПОНЯТИЕ ТИПА ДАННЫХ. ПЕРЕМЕННЫЕ И КОНСТАНТЫ. ОПЕРАЦИЯ ПРИСВАИВАНИЯ.

Всякая программа, предназначенная для реализации на ЭВМ, представ­ляет собой формальное описание алгоритма решения той или иной задачи. Действия, выполняемые программой в соответствии с этим алгоритмом, направлены на преобразование некоторых объектов, определяющих текущее состояние процесса решения задачи. Такие внутренние объекты программы принято называть данными. Для хранения всякого элемента данных выде­ляется необходимое пространство в оперативной памяти ЭВМ, размер ко­торого мы будем называть длиной этого элемента.

Важнейшей характеристикой любого элемента данных является его тип. Понятие типа включает в себя следующую информацию об элементе данных:

- допустимый набор значений, которые объект этого типа может при­нимать в процессе работы программы (совокупность всех указанных зна­чений будем называть областью определения типа);

- состав операций, которые разрешено выполнять над объектами дан­ного типа;

- способ представления элемента данных рассматриваемого типа в памяти машины;

- правила выполнения всякой операции из допустимого для этого типа набора операций.

Язык Си обеспечивает возможность представления и обработки данных следующих основных типов:

- целые числа различной длины со знаком и без;

- вещественные числа различной длины;

- символы, представимые в формате стандарта ASCII.

Те элементы данных, которые сохраняют неизменные значения напротя­жении всего времени работы программы, принято называть константами. Другие же объекты, являющиеся предметом изменения в ходе выполнения алгоритма, называются переменными. С точки зрения языка Си, всякая переменная величина отождествляется с ее именем или идентификатором. С позиции же ЭВМ она рассматривается как изменяющееся во времени со­держимое некоторой области оперативной памяти.

Инструкция языка программирования, позволяющая назначать и изме­нять значения переменных, носит название операции присваивания. Для ее обозначения в Си используется символ " = ". Например:

а = 2; b = c = 3*(a + 4);

После выполнения указанных действий переменная а принимает значе­ние, равное 2, а переменные с и b - значение 18.

$ 2. ТИПЫ ДАННЫХ В ЯЗЫКЕ СИ. ОПИСАНИЕ ДАННЫХ В ПРОГРАММЕ.

В простейшем случае инструкция описания данных в Си-программе име­ет следующий формат:

[описатель класса памяти] описатель типа имя1 [ ,имя2 ...];

Для большинства компиляторов с языка Си допустимыми являются сле­дующие описатели типа ( с указанием длины в байтах и области допустимых значений для компьютеров типа IBM PC.

Тип

Семантика и длина

Диапазон значений

char

Символьная со знаком ( 1 )

от

128 до 127

int

Целая ( 2 )

от

32768 до 32767

short

Короткая целая ( 2 )

от

32768 до 32767

long

Длинная целая ( 4 )

от -2147483648

до 2147483647

unsigned char

Символьная без знака ( 1 )

от 0 до 255

unsigned

Целая без знака ( 2 )

от 0 до 65535

unsigned short

Короткая целая без знака ( 2 )

от 0 до 65535

unsigned long

Длинная целая без знака ( 4 )

от 0 до 4294967297

float

Вещественная ( 4 )

3.4е

38 : 3.8е38

double

Двойной точности вещ. ( 8 )

1.7е-308 : 1.7е308

Ключевые слова unsigned, signed, short и long могут быть использо­ваны как модификаторы основных типов данных при построении производ­ных. Например, следующие описания рассматриваются компилятором как эквивалентные:

short int...............short

long int ...............long

unsigned int ...........unsigned

unsigned short int .....unsigned short

unsigned long int ......unsigned long

signed int .............int

signed char ............char

Примеры описаний:

int a, b, c;

float alpha, beta;

Поскольку внутреннее машинное представление данных одих и тех же типов для различных ЭВМ могут быть различными, то возникают опреде­ленные трудности при необходимости обеспечить надлежащую мобильность программного обеспечения. Так, например, всякая переменная типа int на машинах типа IBM PC AT занимает два байта памяти, в то время как для ее представления на VAX-11 требуется четыре байта. Подобные раз­личия могут привести к неправильной работе программ, манипулирующих, например с битовыми цепочками или требующих динамического выделения памяти для хранения переменных. Преодолеть возникающие при этом труд­ности можно, используя, где это необходимо, операцию определения ко­личества памяти, требуемой для представления некоторой переменной или какого-либо типа. В общем случае эта операция выглядит следующим об­разом:

sizeof(name)

где name есть либо идентификатор переменной, либо имя типа данных.

Например:

a = sizeof(int);

Переменная а принимает значение, равное количеству байт памяти, требуемых для представления любой величины типа int, на конкретной ЭВМ.


$ 3. КОНСТАНТЫ В ЯЗЫКЕ СИ.

Константами в языке Си могут быть числа (целые и вещественные), символы и строки символов, которые разрешено использовать в программе в смысле их значения.

3.1. Целые константы.

Целые константы могут быть представлены в трех основных форматах: десятичном [-] десятичные цифры 0 - 9 [ L или l ]

восьмеричном 0цифры 0 - 7[ L или l]

шестнадцатеричном 0xцифры 0-F[L или l]

Компилятор IBM C/2 рассматривает десятичные константы как числа со знаком и присваивает им тип int. Если значение константы превышает наибольшее машинное целое со знаком, то она представляется как длин­ное целое (тип long). Знак минус в записи десятичной константы ин­терпретируется компилятором как арифметическая операция, а сама конс­танта в этом случае является константным арифметическим выражением.

Восьмеричные и шестнадцатеричные константы могут иметь тип int, unsigned, long или unsigned long в зависимости от их абсолютной вели­чины. Если константа допускает представление в виде целого числа стандартной длины, то компилятор присваивает ей тип int. Если же зна­чение константы превышает максимальное положительное число со знаком, представимое как int, но меньше числа, которое без учета знака может быть представлено тем же числом разрядов, что и int, то ей назначает­ся тип unsigned. Аналогично, если константа не может быть представле­на как unsigned, она получает тип long или unsigned long.

Модификатор L или l, непосредственно следующий за записью констан­ты, требует от компилятора ее представления как имеющей тип long или unsigned long независимо от абсолютной величины.

Примеры различных форм записи целых констант:

Десятичная

Восьмеричная

Шестнадцатеричная

10

012

0xa или 0XA

132

0204

0x84

32179

076663

0x7DB3

15L

017L

0xFL


3.2. Константы с плавающей точкой.

Константы с плавающей точкой являются вещественными десятичными числами со знаком. Их запись может включать в себя целую часть, деся­тичную точку, дробную часть, символ экспоненты е или Е и показатель экспоненты в виде целого числа со знаком:

[-]целая часть.[дробная] [E [+ | -]показатель] или

[-][целая часть].дробная [E [+ | -]показатель]

Знак минус перед константой рассматривается компилятором как ариф­метический оператор и поэтому вещественная отрицательная константа по существу является константным арифметическим выражением. В записи ве­щественной константы может отсутствовать либо целая, либо дробная часть (но не обе сразу). Отсутствие десятичной точки допустимо лишь при наличии экспоненты. Примеры возможных форм записи вещественных констант:

15.75 1.575E1 1575e-2 .1575E2 -.175e2 0.137 137. 137.0

Всякая константа с плавающей точкой рассматривается компилятором как имеющая тип double, т.е. представляется с двойной точностью.

3.3. Символьные константы.

Символьная константа представляет собой букву, цифру, знак пунктуации или Esc-последовательность, заключенные в одиночные кавычки:

'D' '7' ' ' '.'

Esc-последовательности состоят из обратной косой черты, за которой следует буква или комбинация цифр. Символы ' и \ также представляются в виде Esc-последовательностей. В языке Си до­пустимы следующие Esc-последовательности:

\n - новая строка \t - горизонтальная табуляция

\v - вертикальная табуляция \b - шаг назад

\r - возврат каретки \f - новая страница

\a - звуковой сигнал \' - одиночная кавычка

\" - двойная кавычка \\ - обратная косая черта

\ddd - символ ASCII в восьмеричном представлении

\xddd - символ ASCII в шестнадцатеричном представлении

Во всех остальных случаях символ \ игнорируется компилятором.

Последовательности вида \ddd и \xddd позволяют представить любой символ ASCII, включая и непечатные символы, в восьмеричном и шестнад­цатеричном формате соответственно. Незначащие нули слева в обоих слу­чаях могут быть опущены.

Значением символьной константы является целое число, отвечающее внутреннему машинному представлению соответствующего символа.

Примеры правильной записи символьных констант:

'A' 'c' '?' '1' '\'' '\\' '\n' '\033' '\10' '\x1F' 'r'

3.4. Строки символов.

Строками в языке Си являются последовательности символов ASCII, заключенные в двойные кавычки:

" [ один или более символов ASCII ] "

Непечатаемые символы ASCII, а также символы " и \ в составе строк должны представляться соответствующими Esc-последовательностями.

Компилятор IBM C/2 заносит символы строки в память ЭВМ в порядке их следования, автоматически добавляя нуль-символ (Esc-последователь­ность \0) в конец строки. Формально допустимой является также пустая строка (""), состоящая во внутреннем представлении из одного символа \0. Примеры записи символьных строк:

"Это строка символов"

"Enter a number between 1 and 100 \n Or press Enter"

"\"Yes, I do\", she said."

Для формирования длинной последовательности символов, занимающей более одной строки на экране терминала, необходимо набрать символ \, нажать клавишу Enter и продолжить ввод символов с новой строки:

" Длинная строка может быть продолжена\

на следующей строке."

Необходимо отметить, что символьная константа, например 'x', не идентична строке "х", содержащей один символ, так как символьная константа занимает в памяти один байт и равносильна своему числовому коду во внутреннем машинном представлении, строка же из одного симво­ла занимает два байта памяти, первый из которых содержит код этого символа, а второй - символ \0.


$ 4. АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ И ВЫРАЖЕНИЯ

Примеры:

b = (c + d) % 4

e = ++b/(g + h)

В данном примере использована префиксная форма оператора ++ и поэ­тому операция деления будет выполнена после фактического увеличения значения переменной b на единицу.

Замечание. В языке Си операция присваивания является полноправной частью любого арифметического выражения и в общем случае имеет формат

выражение1 = выражение2

[ a+b=c*=d ]

Однако, не вдаваясь пока в семантические подробности такой записи, мы будем пользоваться ее упрощенной формой

идентификатор = выражение

Но даже в такую упрощенную схему укладываются достаточно сложные в семантическом отношении выражения вида

h = 28(q + s)/(t = u * v++)

$ 5. ОПЕРАЦИИ ОТНОШЕНИЯ. ЛОГИЧЕСКИЕ ОПЕРАЦИИ И ЛОГИЧЕСКИЕ

ВЫРАЖЕНИЯЮ УСЛОВНАЯ ОПЕРАЦИЯ.

Полный набор операций отношения следующий:

< > <= >= != ==

Результатом всякой операции отношения является числовое значение типа int, отличное от нуля, если сравнение истинно, и нулю в против­ном случае. Таким образом, операции отношения во внутреннем машинном представлении приводят к арифметическому результату. Это дает возмож­ность объединить понятие арифметического, условного и логического вы­ражения в едином понятии "выражение", что очень важно с точки зрения гибкости и "симметричности" языка.

В процессе вычисления значения всякого условного выражения, опера­ции отношения обрабатываются слева направо. Установленный порядок мо­жет быть изменен путем использования круглых скобок. Например:

x < y == z эквивалентно (x < y) == z

в то время как выражение вида

x < (y == z)

отличается от предыдущего порядком выполнения операций < и =.

Для объединения нескольких операций отношения используется набор двуместных логических операций:

&& || !

Логические выражения являются прямым обобщением простых условных выражений. Стандартный порядок их обработки - слева направо. Приори­тет логических опреаций && и || ниже приоритета любой операции отно­шения.

a <=b && b > c ЁЁЁ (a <= b) && ( b > c)

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

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

Простейшей инструкцией языка Си, использующей логические выраже­ния, является условный оператор:

выражение1 ? выражение2 : выражение3

Например, инструкция

abs_x = (x > 0) ? x : -x

присваивает переменной abs_x абсолютное значение переменной х.

$ 6. АВТОМАТИЧЕСКОЕ ПРЕОБРАЗОВАНИЕ ТИПОВ И ОПЕРАЦИЯ ПРИВЕДЕНИЯ.

Если в состав арифметического или условного выражения входят опе­ранды различных типов, то компилятор автоматически выполняет приведе­ние к общему типу. Несмотря на то, что в ряде случаев характер преобразования зависит от вида конкретной операции и типа операндов, существует общий набор стандартных правил преобразования:

1. если операция выполняется над данными двух различных типов, обе величины приводятся к "высшему" типу;

2. в операторе присваивания конечный результат вычисления выраже­ния в правой части приводится к типу переменной , которой должно быть присвоено значение.

Последовательность имен типов, упорядоченных от "высшего" типа к "низшему", выглядит следующим образом: double, float, long, int, short и char. Применение ключевого слова unsigned повышает ранг соот­ветствующего типа данных со знаком.

Кроме этого компилятор Си во всех случаях расширяет короткие опе­ранды до операндов стандартной длины, принятой при выполнении машин­ных операций. Так операнды, имеющие тип float, преобразуются к типу double, операнды типа char и short к типу int, а операнды типа unsigned char и unsigned short - к unsigned.

Наряду с автоматическим преобразованием типов, в языке Си имеется возможность точно указать тип данных, к которому необходимо привести некоторую величину. Эта возможность реализуется в операции приведения типов следующим образом: перед данной величиной в круглых скобках за­писывается имя требуемого типа. Пусть, например, переменная rez имеет тип int. Тогда значение арифметического выражения

rez = 2.7 + 1.5

согласно общим правилам преобразования типов, равно 4. Однако при­менив явным образом операцию приведения типа к обоим операндам в пра­вой части

rez = (int)2.7 + (int)1.5

получим результат, равный 3. зтот пример говорит о необходимости с особой осторожностью относиться ко всевозможным преобразованиям типов операндов.

$ 7. ПРОСТЕЙШИЕ ОПЕРАТОРЫ ЯЗЫКА СИ. СОСТАВНОЙ ОПЕРАТОР.

Арифметические, условные и логические выражения в совокупности об­разуют объекты программы, которые принято называть просто выражения­ми. Этой терминологией подчеркивается равноправие операций различных групп с точки зрения их роли в формировании выражений. Более того, всякому выражению в Си соответствует некоторое числовое значение (за исключением, конечно, тех случаев, когда результат операции считается неопределенным), которое может быть использовано в дальнейшем.

Однако сами по себе выражения любого вида еще не являются закон­ченными инструкциями языка Си. Для обозначения завершенных действий используется понятие оператора. Простейшим оператором языка СИ явля­ется всякое выражение, заканчивающееся точкой с запятой (;). B част­ности, отдельно стоящая точка с запятой интерпретируется компилятором как нуль-оператор. Например, инструкции вида

a = c*(d + e)/4;

f = alfa++;

являющиеся операторами-выражениями, играют роль законченных пред­писаний для исполняющей системы.

Группа из одного или более операторов, заключенных в фигурные скобки, образуют составной оператор или блок. Например, группа из трех операторов

x = 7.5; y = x + 10;

z = (x + y)/7;

рассматривается компилятором как один составной оператор. В прог­рамме на языке Си составные операторы могут быть использованы всюду наравне с простыми операторами.

Пример 1.

#include

#include

/* Печать таблицы символов ASCII */

main()


{int c, symbol=0, lines=0;

char keycode;

for (c=32; c<=255; c++)

{

if (symbols > 3)

{ printf("\n");

symbols = 0;

lines += 1;

}

if (lines > 23)

{ printf (" Для продолжения нажмите любую клавишу\n");

keycode = getch();

lines = 0;

}

printf("%3d (hex %2x) - %c;",c,c,c);

symbols += 1;

}

printf( "\n"); }

Пример 2.

/* Правила выполнения операции деления */

#include

void main()

{float rez;

printf("\n Результат операции 7/3 равен :.3f", rez = 7/3);

printf("\n Результат операции 7.0/3 равен :.3f", rez = 7.0/3);

printf("\n Результат операции 7./3. равен :.3f", rez = 7./3.);

printf("\n Результат операции (float)7/3 равен :.3f",

rez=(float)7/3);

printf("\n Результат операции (float)(7/3) равен :.3f",

rez = (float)(7/3));

}

Пример 3.

/* Опрос клавиатуры и печать расширенных кодов клавишей */

#include

#include

main()

{ int key;

while (1)

{ printf("\t*** Нажмите любую комбинацию ключей ***\n");

key = getch();

if (key != 0)

printf("Код нажатой клавиши = %3d (hex %2)\n",key, key);

else

{ printf("Прочитанный код равен нулю. Выход\n");

break; }

}

printf("\n---------------------------\n");

}

Пример 4.

/* Подсчет количества слов в предложении */

#include

#define OFF 0

#define ON 1

void main()

{

char sym;

int nwords = ON, state = OFF;

printf('\n Введите предложение > \n");

while ((sym = getch()) != '\n')

if(sym == ' ' || sym == ',' || sym == ';' || sym == '.')

state = OFF;

else if(state == OFF)

state = ON; nwords ++

printf("\n\n Количество слов в предложении = %d",nwords);

}