Трактовка имени структуры. Имя структуры обозначает значение всей области памяти, которую она занимает. Поэтому для структур одного и того же типа допускается операция присваивания: goods2 = goods1; При этом вся область памяти goods1 копируется в область памяти goods2. Доступ к элементу структуры. Для этого используется операция ".". goods1.name - образовалось составное имя. Тип составного имени такой же как тип соответствующего элемента структуры. С составным именем можно выполнять любые действия, разрешенные для типа элемента. goods2.price = 20*goods1.price; scanf("%s", goods1.name); goods1.name[3]; Из структур можно составить массив: GOODS ab[50]; Тогда ab - адрес массива; ab[2] - значение структуры; ab[2].price - значение элемента структуры. Структура может входить в другую структуру: typedef struct { GOODS goods; int fl;} GF; GF a - описание; a.good.name Никаких ограничений на уровень вложенности структур нет. Инициализация структур. Статические структуры могут быть проинициализированы подобно массивам: static GOODS a = { "Телепвизор", 14000.0, 20}; Необходимо строго следитьза соответствием порядка констант порядку элементов структуры. Структуры и функции. Структура целиком может быть передана функции как параметр. Кроме того, структура может быть полностью возвращена как значение функции. Пример: typedef struct { double r, f;} POLAR; typedef struct { double x, y;} DECART; DECART ptod(POLAR pcoord) { DECART dcoord; dcoord.x = pcoord.r*cos(pcoord.f); dcoord.y = pcoord.r*sin(pcoord.f); return dcoord; } void main(void) { DECART a; POLAR b = { 15.2, 0.18}; a = ptod(b); . . . } Для больших структур такой способ передачи параметров и возврата значений неэффективен, так как компилятору приходится создавать копии параметров и результатов работы функции в специальной области памяти. Значиительно эффективнее передавать адреса параметров: void prot (DECART*dc, POLAR*pc) { (*dc).x = (*pc).r*cos((*pc).f); (*dc).y = (*pc).r*cos((*pc).f); } (*dc) в скобках потому, что "." имеет более высший приоритет. Головная программа при этом выглядит так: void main(void) { DECART a; POLAR b = { 15.2, 0.18}; ptod(&a, &b); . . . } Запись вида (*dc).x громоздка и плохо понятна. Поэтому разработчики языка C предусмотрели более понятную эквивалентную запись: (*dc).x эквивалентно dc->x. Используя ее: void ptod(DECART *dc, POLAR *pc) { dc->x = pc->r*cos(pc->f); dc->y = pc->r*sin(pc->f); } Поля бит в структурах. Для целых чисел допускается использовать область памяти меньше байта: struct { int c1:4; -8<c1<7 int c2:12 -2 <c2<2 -1 } ab; ab.c1 будет преобразовано в целый тип, затем будет использоваться. На преобразование тратится время и память. Рекомендуется использовать для беззнаковых типов данных и в крайних случаях. /* Пример использования структур */ #include <stdio.h> #include <string.h> #include <math.h> 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<n; 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<n-1; i++) for(j=i+1; j<n; j++) if( gs[i].price ) { r=gs[j]; gs[j]=gs[i]; gs[i]=r; } } Объединения. Объединяются ключевым словом union. Способы описания такие же, как и в случае структур, только вместо слова struct используется слово union. union {int a; long b;} pr; Для переменной pr выделяется память, достаточная для хранения самого длинного элемента объединения, т. е. в нашем примере - 4 байта. Если использовать pr.a, то выделенная память будет использоваться как int, в случае pr.b как long. Однако, участок памяти один и тот же. Поэтому одновременно существовать pr.a и pr.b не могут. Ответственность за некорректное использование памяти лежит на программисте. Объединения используются для экономии памяти: union {int bc[100]; double kk[20];} cc; На все отводится 200 байт. int bc[100] 200 байт ______________________________ |----------------------------| double kk[20] (160 байт) Одновременно работать с массивом cc.bc и cc.kk нельзя. Объединения нельзя инициализировать. |