Главная страница

Лекции Булатицкий Дмитрий Иванович (во многом по материалам Прасолова А. Н.)


Скачать 319.62 Kb.
НазваниеЛекции Булатицкий Дмитрий Иванович (во многом по материалам Прасолова А. Н.)
Дата11.01.2022
Размер319.62 Kb.
Формат файлаdocx
Имя файлаLecture_Programming_2021_09_01.docx
ТипЛекции
#328427
страница23 из 36
1   ...   19   20   21   22   23   24   25   26   ...   36

Многомерные массивы


В языке Си допускается использовать не только двумерные, но и трехмерные, четырехмерные и т. д. массивы. Их использование ничем принципиально не отличается от использования двумерных массивов, однако на практике они применяются значительно реже.
    1. Вложенные структуры

    2. Поля бит в структурах


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

struct {

int c1:4; -8

int c2:12 -2

} ab;

ab.c1 будет преобразовано в целый тип, затем будет использоваться. На преобразование тратится время и память. Рекомендуется использовать для беззнаковых типов данных и в крайних случаях.
/* Пример использования структур */
#include

#include

#include
typedef struct {

char name[21];

int number;

float price;

} GOODS;
void in_goods ( GOODS gs[], int *n );

int in_goods1 ( GOODS *g );

void out_goods ( GOODS gs[], int n );

void sort_goods ( GOODS gs[], int n);
void main( void )

{

int n; GOODS goods[100];

in_goods ( goods, &n );

sort_goods ( goods, n );

out_goods ( goods, n );

{ float f=0; sin(f); }

}
void in_goods( GOODS gs[], int *n)

{

printf("Введите характеристики товаров в виде:\n" \

"наименование количество цена\n" \

"-----окончание ввода \"end\"-------\n");

*n=0;

while( in_goods1(&gs[*n]) ) (*n)++;

}

int in_goods1( GOODS *g )

{

scanf( "%s", g->name );

if ( strcmp(g->name, "end")==0 ) return 0;

scanf( "%d%f", &g->number, &g->price );

return 1;

}

void out_goods( GOODS gs[], int n )

{

int i;

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

printf("| Наименование | Кол-во | Цена |\n");

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

for( i=0; i

printf( "| %20s | %6d | %10.2f |\n",

gs[i].name, gs[i].number, gs[i].price );

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

}
void sort_goods( GOODS gs[], int n )

{

int i, j, GOODS r;

for (i=0; i

for(j=0; j

if( gs[j].price < gs[j+1].price )

{ r=gs[j]; gs[j]=gs[j+1]; gs[j+1]=r; }

}
    1. Объединения


Объединяются ключевым словом union. Способы описания такие же, как и в случае структур, только вместо слова struct используется слово union.

union {int a; long b;} pr;

Для переменной pr выделяется память, достаточная для хранения самого длинного элемента объединения, т. е. в нашем примере – 4 (8) байта.

Если использовать pr.a, то выделенная память будет использоваться как int, в случае pr.b как long. Однако, участок памяти один и тот же. Поэтому одновременно существовать pr.a и pr.b не могут. Ответственность за некорректное использование памяти лежит на программисте. Объединения используются для экономии памяти:

union {int bc[100]; double kk[20];} cc;

На все отводится 200 (400) байт.

int bc[100] 200 байт

______________________________

|----------------------------|

double kk[20] (160 байт)

Одновременно работать с массивом cc.bc и cc.kk нельзя.

Объединения нельзя инициализировать.

  1. Дополнительные сведения о функциях

    1. Время жизни переменных и классы памяти языка Си


Время жизни переменных программы определяется классом памяти. В языке Си принято различать статические (static), автоматические (auto) и динамические данные.

Статические переменные создаются и инициализируются в момент запуска программы в сегменте статических данных и существуют до ее останова, не меняя своего местоположения в памяти ЭВМ.

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

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

#include
void fun(void)

{

static int first = 1;

if( first )

{

printf("Это первый вызов функции.\n");

first = 0;

}

else

printf("Это не первый вызов функции.\n");

}
void main(void)

{

fun(); fun(); fun();

}

Статическая переменная first функции fun() создается и инициализируется при запуске программы, до выполнения функции main(). Поэтому, при первом вызове функции fun() значение first равно 1, при последующих вызовах fun() переменная first будет сохранять свое значение, измененное функцией fun() на 0. Подобным же образом можно организовать подсчет числа обращений к функции.

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

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

Если в предыдущем примере убрать ключевое слово static из описания переменной first, то функция fun() при каждом вызове будет вести себя как и при первом. Это происходит потому, что переменная first стала автоматической, создается и инициализируется при каждом вызове функции fun().

Глобальные данные не могут быть автоматическими, потому что нет блока, которому они принадлежат.

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

    1. 1   ...   19   20   21   22   23   24   25   26   ...   36


написать администратору сайта