Лекции Булатицкий Дмитрий Иванович (во многом по материалам Прасолова А. Н.)
Скачать 319.62 Kb.
|
Многомерные массивыВ языке Си допускается использовать не только двумерные, но и трехмерные, четырехмерные и т. д. массивы. Их использование ничем принципиально не отличается от использования двумерных массивов, однако на практике они применяются значительно реже. Вложенные структурыПоля бит в структурахДля целых чисел допускается использовать область памяти меньше байта: 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; } } ОбъединенияОбъединяются ключевым словом 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 нельзя. Объединения нельзя инициализировать. Дополнительные сведения о функцияхВремя жизни переменных и классы памяти языка СиВремя жизни переменных программы определяется классом памяти. В языке Си принято различать статические (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) с помощью специальных функций менеджера памяти, которые рассмотрим ниже в специальном разделе.
|