Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Технология программиования_Си.docx
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
33 Кб
Скачать
☆

Операции со структурными переменными

Все структурные типы обладают рядом общих операций

  1. Взятие адреса структурной переменной struct my_struct { int field1; float field2: } x; &x

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

  3. Переменную структурного типа можно передавать в качестве аргумента в функцию и возвращать из функции. Можно так же передавать указатель на структурную переменную my_struct f(my_struct ms)

Структура может иметь большие размеры. Если аргумент функции имеет структурный тип, то при вызове функции будет создана копия структуры, а это потребует время и место в памяти, поэтому обычно в функции передаются указатели на структуры.

Инициализация структур

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

struct complex {

float real;

float imag;

};

struct complex z={1.2, -5};

struct complex z1={1};

Статические глобальные структурные переменные по обычным правилам обнуляются.

struct test {

int a[3];

int b;

};

struct test z2={1,2,3,4};

// struct (a — 1,2,3; b — 4)

Struct test z3 = {{1,2},4};

Есть возможность определять массивы структур, причём эти массивы можно инициализировать по обычным правилам.

struct complex z4[] = {{1}, {2,3}, {4,5}};

struct complex z5[3]={1,2,3,4,,5};

z5[3]={{1,2},{3,4},{5}};

Операции со структурами

Доступ к полям структуры

Структуры – это агрегатный тип, который строится из данных разных типов. Каждое поле (элемент структуры) имеет имя.

Есть два способа обратиться к отдельному полю. Если мы имеем структурную переменную, то для обращения к отдельным полям используется операция «.» (точка).

struct complex z, *pz=&z;

z.real, z.imag

(*pz).real, (*pz),imag

Если доступ к полю осуществляется через указатель, то применяется операция «стрелка» (->)

pz->real, pz->imag

Вычисление размера структуры

К структурному типу и структурным переменным можно применять операцию sizeof.

sizeof(struct, complex)

sizeof(z)

Вообще говоря, размер структурного типа можно посчитать как сумму размеров его полей, однако реально этот размер может оказаться больше. Процессор хорошо обрабатывает информацию, которая представлена машинными словами. Однако, структура может содердать поля, которые занимают одно из машинных слов не полностью. Предположим, что в системе с 4-байтнм машинным словом определён структурный тип. Массив s займёт оно машинное слово и один байт из следующего. Если экономить память, то поле b так же будет расположено в двуз машинных словах. Такое расположение данных снизит скорость обработки. Обычно для тсруктур данных выполняется выравнивание полей на границу машинного слова. При этом могут быть небольшие потери памяти, но зато серьёзный выигрыш в производительности. В результате размер структурного типа будет несколько больше, чем сумма размеров его полей.

struct test {

char s[5];

int b;

}

Sizeof возвращает тот размер памяти, который нужен будет после выравнивания на границу машинного слова.

Оператор typedef (type definition)

После определения структурного типа, его везде нужно использовать вместе со служебным словом struct. Это утяжеляет текст программы, поэтому в Си добавлен оператор typedef, позволяющий создавать простые синонимы для имён структурных типов.

typedef struct {int x; int y;} point;

typedef struct {point p1,p2;} rect;

int square(rect z) { return(z.p2.x-z.p1.x)*(z.p2.y-z.p1.y); }

Файловый ввод-вывод

Потоки

Программа может считывать данные из каких то источников и выводить данные на экран, файл или другие устройства. Чтобы управлять этими операциями, система программирования должна предлагать соответствующие функции. Так как имеется большое разнообразие устройств ввода-вывода, то создать библиотеку, позволяющую работать с любым из них невозможно. Кроме того, ориентация на конкретные устройства будет ограничивать переносимость программы. При разработке языка Си было предложено для выполнения операций ввода-вывода использовать понятие абстрактного потока. Т.е. программа всегда вводит или выводит данные из потоков, которые не привязаны к конкретным устройствам и являются универсальными. Взаимодействие с физическими устройства обеспечивается ОС с помощью драйверов. Система программирования должна обладать функциями, которые позволяют работать с потоками. В Си – две таких библиотеки. Библиотека стандартного уровня предлагает набор высокоуровневых функций, позволяющих программисту работать с потоками, не вникая в мелкие детали взаимодействия. Библиотека системного уровня позволяет программировать тонкие детали операций ввода-вывода. Ею пользуются в основном при системном программировании, когда необходимо добиться максимально высокой скорости выполнения операций, экономии памяти и т.д.

Fopen, fread, fwrite – стандартный уровень

Open, read, write – системный уровень.

Различают буферизованные и не буферизованные операции ввода-вывода. Буферизация подразумевает, что обмен информации ведётся через некоторую промежуточную область памяти, которая называется буфером и создаётся в оперативной памяти. Буферизация позволяет повысить быстродействие операций ввода-вывода, потому что они выполняются реже и бОльшими блоками.

Потоки различаются по типу передаваемой информации на текстовые и двоичные. В разных операционных системах имеются небольшие отличия при сохранении текстовой информации. Например, в Windows конец строки обозначается двумя кодами, а в Linux – одним. В Windows есть специальный признак конца файла, в Linux – нет. Поэтому, когда происходит чтение или запись текстовой информации, итоговые файлы будут немного различаться. При обработке текстовых файлов из Linux в Windows могут быть добавлены дополнительные коды (и наоборот). Для текстовых файлов эти операции безопасны, однако по внешнему виду отличить текстовый файл от двоичного – невозможно. Например, в двоичном файле могут встретиться коды 10,13 (двоичные коды, связанные с переводом строки) которые никак не связаны с переводом строки. Очевидно, что никакие преобразования здесь недопустимы. Функции ввода и вывода по-разному работают с текстовыми и двоичными потоками.