C++ Структури. Основни операции

Програмите са компилирани на Borland C++

Структури. Основни операции.
Структура – наредена съвкупност от краен брой елементи от различен тип, която има йерархична организация;
описанието на типа структура:
struct идентификатор
{ описание_на_първи_елемент_от_данни;
  описание_на_първи_елемент_от_данни;
  ...
  описание_на_последен_елемент_от_данни;
} ;
Отделните елементи от данни още се наричат полета от данни; при компилиране на описанието на типа структура не се резервира памет за полетата;

пример:
struct time
 {  int hour;
    int min;
    float sec;
 } ;
променливите от тип структура могат да се дефинират по два начина:
дефинирането става заедно с описанието на типа структура; например:
struct time
{ int hour;
  int min;
  float sec;
} u, v, t;
тук u, v, t са променливи от тип структура (структурни променливи); ако сме дефинирали структурни променливи, можем да изпуснем името на структурата, но в такъв случай, ако се наложи допълнително да се дефинират променливи от тази структура, тя отново трябва да се опише;
дефинирането става отделно, след описанието на структурата;
например:
struct time
{ int hour;
  int min;
  float sec;
} ;
struct time u, v, t;
тук дефинираме променливи u, v, t от тип структура time;
в C++ резервираната дума struct може да се изпусне в дефиницията на структурни променливи, но в C не може;
името на типа на структурата и имената на полетата на структурата от една страна и имената на произволни
променливи от друга страна могат да съвпадат; имената на отделните полета трябва да са различни помежду си;
полетата на дадена структура се разполагат последователно в оперативната памет; при обработване на дефиниция на структурна променлива, компилаторът ще разпредели памет, достатъчна за да могат да се запишат всичките полета на структурата;
броят на байтовете, които се разпределят за една променлива от тип структура не е винаги равен на сумата от дължината на отделните полета, заради влиянието на друг фактор, който се нарича подравняване на даннитеStructure Alignment; подравняването се задава от опциите на компилатора;
при 16-битовите компилатори може да се подравнява по байт или по дума (една дума е два байта);
при 32-битовите компилатори има възможност за подравняване по двойна или по четворна дума;
ако подравняването е по граници на байт, тогава полетата са разположени едно след друго и дължината на структурата ще е сума от дължините на отделните полета;
при друго подравняване компилаторът разполага между отделните полета на една структурна променлива и между елементите на масив празни байтове, така че да се изпълняват следните условия:
отделната структурна променлива, в частност когато тя е елемент на масив, да започва на границата на дума, двойна дума или четворна дума; това значи, че тази граница трябва да се дели на 2, на 4 или на 8;
всеки тип, различен от char, да започва на границата на дума – двойна или четворна;
при необходимост в края на структурата се добавят празни байтове, така че общият брой байтове на структурата да е кратен на 2, 4 или на 8;
точният брой байтове на една структура може да се получи с операцията sizeof; например:
sizeof (struct time) – при 16-битов компилатор, hour, min заемат по 2  байта, sec заема 4 байта; ако подравняването е по дума, структурата ще заема 8 байта; ако подравняването е по двойна дума, в края на hour и в края на min ще се добавят по два празни байта;
цел на Structure Alignmentда се даде възможност за оптимизация; ако за потребителя е важна икономията на памет, тогава може да се използва подравняване по байтове; ако потребителят търси по-голяма ефективност, тогава може да се използва подравняването по двойна или четворна дума – остават свободни байтове и се хаби памет, но реализацията е по-бърза;

Основни операции със структури
Адресна операция – определя се адреса на една структурна променлива; няма разлика от обикновените променливи;
struct time *p;
p е указател от тип структура time;
p = &u;
на p се присвоява адреса на u;
Друга основна операция е обръщение към полетата на структурата;
тя се осъществява по два начина:
чрез съставен оператор като се използва оператор ‘.’ –
синтаксис:
идентификатор_на_структура . идентификатор_на_поле
пример:
struct time x;
int k, n;
k = x.hour;
x.hourполето hour от структурната променлива x
n = x.min;
тази операция можем да я използваме с псевдоними:
struct time &newx = x;
k = newx.hour;
n = newx.min;
стойностите на k и n ще са същите както по-горе;
чрез използване указател към структурна променлива;
синтаксис:
указател_към_структурна_променлива -> идентификатор_на_поле
пример:
struct time *p;
p = &u;
n = p -> hour;
k = p -> min;
операциите ‘.’ и ‘->’ са взаимозаменяеми;
например:
n = x.hour;
n = (&x) -> hour;
n = (*p) -> hour;
операцията ‘.’ осъществява пряк достъп до полето на една структурна променлива, а операцията ‘->’ осъществява косвен достъп; и двете операции имат приоритет 1 (най-високия) и са ляво-асоциативни; по тази причина слагаме скоби;
променливите от тип структура могат да бъдат инициализирани – след дефинирането на променливата се поставя знак за присвояване и във фигурни скоби се записват началните стойности на полетата от структурата; началните стойности се присвояват в реда в който са описани;
пример:
struct time example = { 5, 355, 25, 66};
ако за структурната променлива се разпределя памет в областта за статични данни, началните стойности трябва да са константи; ако не сме задали стойности за всички полета, останалите получават стойност 0; ако началните стойности са повече от полетата – съобщение за грешка;
със структурни променливи от един и същи тип може да се извърши операция присвояване;
например:
u = v; //при горните дефиниции;
при такава операция стойностите на полетата на структурната променлива отдясно се присвояват на полетата на променливата отляво; по-точно се осъществява физическо копиране на толкова байтове, колкото е размера на съответната структура;

Вложени структури. Рекурсивно използване на структури.
Тип на структура може да включва като полета други структури; те от своя страна също могат да притежават структурни полета и т.н.
например:
struct person
 { char name[30];
  int born, died;
};
struct book
 { char name[40];
   struct person author;
   int year;
   float price;
 };
ако вложената структура е дефинирана предварително (както по-горе), тя може да се използва за дефиниране на отделни структурни променливи;
struct book b1, b2, *pb;
struct person per1, per2, *ptrper;
има възможност самата дефиниция да е вложена:
struct book
{ char name[40];
  struct person
   { char name[30];
     int born, died;
   } author;
  int year;
  float price;
}
в този пример имаме вложена дефиниция, като областта на видимост на вложени я тип структура е дефиницията на включващата го структура и той не може да се използва за дефиниране на самостоятелни структурни променливи; в такъв случай става безсмислено указването на име на вложения тип структура;
достигане на полетата при вложени структури:
b1.author.name, b1.author.bornприлагане на операцията ‘.’ два пъти (тя е ляво-асоциативна);
pb = &b1;
int p;
p = pb->author.born; - комбиниране на операция ‘->’ с операция ‘.’;
реално операцията ‘->’ тук не е нужна; има случаи, когато е нужно използването на -> - когато е известен адресът, но не и името на променливата;
поле на структура може да бъде указател;
пример:
struct point
 { int k;
   int *p;
   int *q;
 } ;
struct point var; //дефиниране на структурна променлива от тип
  point;
обръщането към полетата на променливата var, които са указатели се осъществява по общоприетия начин: var.p, var.q; полетата, които са указатели могат да участват във всички допустими адресни операции; например:
*var.pтова е стойността, записана в адреса, сочен от указателя p; не поставяме скоби, защото операция ‘.’ е с по-голям приоритет;
типът на указателите, описани в тялото на структурата може да е всеки допустим тип, включително и структура; C и C++ не допускат поле от една структура да бъде структура от същия тип;
няма проблеми поле, което е указател да сочи към структура от същия тип; например:
struct linkedlist
 { int field;
   struct linkedlist *next;
 } ;
в такъв случай говорим за рекурсивно използване на структура; чрез него могат да се създават и обработват данни, организирани в списъци, или имащи дървовидна структура; обикновено, при тях се използва динамично заделяне на памет;

Коментари: