Variabele int. Gegevenstypen in C-taal

Gegevenstypen

Gegevenstypen zijn vooral belangrijk in C# omdat het een sterk getypeerde taal is. Dit betekent dat alle bewerkingen onderworpen zijn aan strikte typecontrole door de compiler en dat illegale bewerkingen niet worden gecompileerd. Daarom elimineert strikte typecontrole fouten en verhoogt de betrouwbaarheid van programma's. Om typecontrole af te dwingen, moeten alle variabelen, expressies en waarden van een specifiek type zijn. Er bestaat helemaal niet zoiets als een “typeloze” variabele in deze programmeertaal. Bovendien bepaalt het type waarde de bewerkingen die erop kunnen worden uitgevoerd. Een bewerking die legaal is voor het ene gegevenstype, is mogelijk niet geldig voor een ander gegevenstype.

Er zijn twee algemene categorieën ingebouwde gegevenstypen in C#: waarde typen En referentie typen. Ze verschillen in de inhoud van de variabele. Conceptueel gezien is het verschil tussen de twee dat een waardetype gegevens rechtstreeks opslaat, terwijl een referentietype een verwijzing naar een waarde opslaat.

Deze typen worden op verschillende locaties in het geheugen opgeslagen: waardetypen worden opgeslagen in een gebied dat bekend staat als de stapel, en referentietypen worden opgeslagen in een gebied dat bekend staat als de beheerde heap.

Laten we eens kijken waarde typen.

Typen gehele getallen

C# definieert negen typen gehele getallen: char, byte, sbyte, kort, ushort, int, uint, lang en ulong. Maar het char-type wordt voornamelijk gebruikt om karakters weer te geven en wordt daarom afzonderlijk behandeld. De overige acht typen gehele getallen zijn bedoeld voor numerieke berekeningen. Hieronder vindt u hun reeks cijfers en bitdiepte:

C# gehele typen
Type Typ CTS Beetje maat Bereik
byte Systeem.Byte 8 0:255
sbyte Systeem.SByte 8 -128:127
kort Systeem.Int16 16 -32768: 32767
kort Systeem.UInt16 16 0: 65535
int Systeem.Int32 32 -2147483648: 2147483647
uint Systeem.UInt32 32 0: 4294967295
lang Systeem.Int64 64 -9223372036854775808: 9223372036854775807
lang Systeem.UInt64 64 0: 18446744073709551615

Zoals de bovenstaande tabel laat zien, definieert C# zowel ondertekende als niet-ondertekende varianten van de verschillende typen gehele getallen. Typen gehele getallen met teken verschillen van hun niet-ondertekende tegenhangers in de manier waarop ze het meest significante deel van het gehele getal interpreteren. Als een programma dus een geheel getal met teken specificeert, genereert de C#-compiler code die het meest significante bit van het gehele getal als tekenvlag gebruikt. Een getal wordt als positief beschouwd als de tekenvlag 0 is, en negatief als deze 1 is.

Negatieve getallen worden bijna altijd weergegeven met de twee-complementmethode, waarbij alle binaire cijfers van het negatieve getal eerst worden omgekeerd en vervolgens 1 bij dat getal wordt opgeteld.

Waarschijnlijk het meest voorkomende gehele type bij het programmeren is int-type. Variabelen van het type int worden vaak gebruikt voor luscontrole, array-indexering en wiskundige berekeningen voor algemene doeleinden. Wanneer u een geheel getalwaarde nodig heeft met een groter bereik aan getalrepresentaties dan het int-type, zijn er voor dit doel een aantal andere geheeltallige typen beschikbaar.

Dus als de waarde zonder teken moet worden opgeslagen, kunt u selecteren uint-type, voor grote ondertekende waarden - lange soort, en voor grote niet-ondertekende waarden - type lang. Hieronder staat als voorbeeld een programma dat de afstand van de aarde tot de zon in centimeters berekent. Om zo’n grote waarde op te slaan, wordt een lange variabele gebruikt:

Systeem gebruiken; met behulp van System.Collections.Generic; met behulp van System.Linq; met behulp van System.Text; naamruimte ConsoleApplication1 ( class Program ( static void Main(string args) ( lang resultaat; const long km = 149800000; // afstand in km. resultaat = km * 1000 * 100; Console.WriteLine(resultaat); Console.ReadLine(); ) ) )

Aan alle integer-variabelen kunnen waarden worden toegewezen in decimale of hexadecimale notatie. In het laatste geval is een voorvoegsel 0x vereist:

Lange x = 0x12ab;

Als er enige onzekerheid bestaat over de vraag of een geheel getal van het type int, uint, long of ulong is, dan standaard int wordt geaccepteerd. Om expliciet aan te geven welk ander geheel getal een waarde moet hebben, kunnen de volgende tekens aan een getal worden toegevoegd:

Uint ui = 1234U; lange l = 1234L; ulong ul = 1234UL;

U en L kunnen ook in kleine letters worden geschreven, hoewel een kleine letter L visueel gemakkelijk kan worden verward met het cijfer 1 (één).

Drijvende-kommatypen

Met typen met drijvende komma kunt u getallen weergeven met een gebroken deel. Er zijn twee soorten drijvende-kommagegevenstypen in C#: vlot En dubbele. Ze vertegenwoordigen numerieke waarden met respectievelijk enkele en dubbele precisie. De breedte van het float-type is dus 32 bits, wat ongeveer overeenkomt met het weergavebereik van getallen van 5E-45 tot 3,4E+38. En de breedte van het dubbele type is 64 bits, wat ongeveer overeenkomt met het weergavebereik van getallen van 5E-324 tot 1,7E+308.

Het gegevenstype float is bedoeld voor kleinere drijvende-kommawaarden die minder precisie vereisen. Het dubbele datatype is groter dan float en biedt een hogere mate van nauwkeurigheid (15 bits).

Als een niet-gehele waarde hardgecodeerd is in de broncode (bijvoorbeeld 12.3), gaat de compiler er gewoonlijk van uit dat een waarde van het type double bedoeld is. Als de waarde moet worden opgegeven als een float, moet u er het F-teken (of f) aan toevoegen:

Vlotter f = 12,3F;

Decimaal gegevenstype

Er is ook een decimaal type beschikbaar om drijvende-kommagetallen met hoge precisie weer te geven. decimale, dat bedoeld is voor gebruik bij financiële berekeningen. Dit type heeft een breedte van 128 bits om numerieke waarden weer te geven variërend van 1E-28 tot 7,9E+28. U bent zich er waarschijnlijk van bewust dat reguliere berekeningen met drijvende komma gevoelig zijn voor decimale afrondingsfouten. Deze fouten worden geëlimineerd door het decimale type te gebruiken, waardoor getallen tot 28 (en soms 29) decimalen kunnen worden weergegeven. Omdat dit datatype decimale waarden kan weergeven zonder afrondingsfouten, is het vooral handig voor financieel gerelateerde berekeningen:

Systeem gebruiken; met behulp van System.Collections.Generic; met behulp van System.Linq; met behulp van System.Text; naamruimte ConsoleApplication1 ( class Program ( static void Main(string args) ( // *** Berekening van de kosten van een investering met *** // *** vast rendement*** decimaal geld, procent; int i; const byte jaren = 15; geld = 1000,0 miljoen; procent = 0,045 miljoen;

Het resultaat van dit programma zal zijn:

Symbolen

In C# worden tekens niet weergegeven in 8-bits code, zoals in veel andere programmeertalen zoals C++, maar in 16-bits code, genaamd Unicode. De tekenset van Unicode is zo breed dat deze tekens uit bijna elke natuurlijke taal ter wereld omvat. Hoewel veel natuurlijke talen, waaronder Engels, Frans en Duits, relatief kleine alfabetten hebben, gebruiken sommige andere talen, zoals het Chinees, vrij grote tekensets die niet kunnen worden weergegeven door een 8-bits code. Om deze beperking te omzeilen, definieert C# typ char, wat niet-ondertekende 16-bits waarden vertegenwoordigt, variërend van 0 tot 65.535. De standaard 8-bits ASCII-tekenset is echter een subset van Unicode, variërend van 0 tot 127. Daarom zijn ASCII-tekens nog steeds geldig in C#.

Dit spiekbriefje geeft informatie over de belangrijkste gegevenstypen van de programmeertaal C++ en de kenmerken van hun implementatie. Aan het einde van het record bevindt zich ook een tabel met de waardenbereiken van deze typen.

Gegevenstypeconcept

Het hoofddoel van elk programma is het verwerken van gegevens. Verschillende soorten gegevens worden verschillend opgeslagen en verwerkt. In elke algoritmische taal moet elke constante, variabele, uitdrukking of functie een specifiek type hebben.

Het gegevenstype definieert:

  • interne weergave van gegevens in computergeheugen;
  • de reeks waarden die hoeveelheden van dit type kunnen aannemen;
  • bewerkingen en functies die kunnen worden toegepast op de grootheden van dit type.

Op basis van deze kenmerken selecteert de programmeur het type van elke grootheid die in het programma wordt gebruikt om echte objecten weer te geven. Met een vereiste typedeclaratie kan de compiler de geldigheid van verschillende programmaconstructies controleren. Het type waarde bepaalt de machine-instructies die zullen worden gebruikt om de gegevens te verwerken.

Alle soorten C++-talen kunnen worden onderverdeeld in eenvoudig En composiet . De C++-taal definieert er zes voornaamst gegevenstypen om gehele getallen, reële waarden, karakterwaarden en logische waarden weer te geven. Op basis van deze typen kan de programmeur een beschrijving invoeren composiet typen. Deze omvatten arrays, opsommingen, functies, structuren, referenties, pointers, unies en klassen.

Basisgegevenstypen in C++

Basisgegevenstypen (standaard) worden vaak rekenkundig genoemd omdat ze kunnen worden gebruikt bij rekenkundige bewerkingen. Om de belangrijkste typen te beschrijven, worden de volgende gedefinieerd:

  1. int(int);
  2. teken(teken);
  3. wchar_t(breedchar);
  4. bool(booleaans);
  5. zweven(echt);
  6. dubbel (dubbele precisie echt).

De eerste vier typen worden integer ( geheel ), de laatste twee - typen met drijvende komma . De code die de compiler genereert voor het verwerken van gehele waarden is anders dan de code voor drijvende-kommawaarden.

Er zijn er vier typespecificatie , verduidelijking van de interne representatie en het bereik van waarden van standaardtypen:

  • kort (kort);
  • lang(lang);
  • ondertekend(ondertekend);
  • niet ondertekend.

Type geheel getal (int)

De grootte van het int-type wordt niet gedefinieerd door de standaard, maar is afhankelijk van de computer en de compiler. Voor een 16-bits processor worden 2 bytes toegewezen voor waarden van dit type, voor een 32-bits processor - 4 bytes.

De korte specificatie vóór de typenaam geeft aan de compiler aan dat er 2 bytes moeten worden toegewezen aan het nummer, ongeacht de processorcapaciteit. De lange specificatie betekent dat de gehele waarde 4 bytes in beslag neemt. Op een 16-bits computer zijn de equivalenten dus int en short int, en op een 32-bits computer zijn de equivalenten int en long int.

Interne vertegenwoordiging waarden van het type geheel getal - een geheel getal in binaire code. Wanneer u de ondertekende specificatie gebruikt, wordt het meest significante bit van het getal geïnterpreteerd als ondertekend (0 is een positief getal, 1 is een negatief getal). Met de niet-ondertekende specificatie kunnen alleen positieve getallen worden weergegeven, aangezien het meest significante bit wordt behandeld als onderdeel van de code van het getal. Het bereik van waarden van het type int hangt dus af van de specificaties. De waardenbereiken van waarden van het gehele type met verschillende specificaties voor IBM PC-compatibele computers worden gegeven in de tabel "Waardebereiken van eenvoudige gegevenstypen" aan het einde van de invoer.

Standaard worden alle typen gehele getallen als ondertekend beschouwd, wat betekent dat de ondertekende specificatie kan worden weggelaten.

Constanten die in een programma worden gevonden, krijgen afhankelijk van hun type het ene of het andere type toegewezen. Als de programmeur om de een of andere reden niet tevreden is met dit type, kan hij het vereiste type expliciet aangeven met behulp van de achtervoegsels L, l (lang) en U, u (niet-ondertekend). De constante 32L zal bijvoorbeeld van het type long zijn en 4 bytes in beslag nemen. U kunt de achtervoegsels L en U tegelijkertijd gebruiken, bijvoorbeeld 0x22UL of 05Lu.

Opmerking

De typen korte int, lange int, ondertekende int en niet-ondertekende int kunnen worden afgekort tot respectievelijk kort, lang, ondertekend en niet-ondertekend.

Tekentype (char)

Aan de waarde van een tekentype wordt een aantal bytes toegewezen dat voldoende is om elk teken uit de tekenset voor een bepaalde computer te huisvesten, wat de naam van het type bepaalt. Meestal is dit 1 byte. Het char-type kan, net als andere typen gehele getallen, ondertekend of niet-ondertekend zijn. Ondertekende waarden kunnen waarden opslaan in het bereik van -128 tot 127. Met behulp van de niet-ondertekende specificatie kunnen waarden variëren van 0 tot 255. Dit is voldoende om elk teken in de ASCII-tekenset van 256 tekens op te slaan. Waarden van het char-type worden ook gebruikt om gehele getallen op te slaan die de grenzen van de opgegeven bereiken niet overschrijden.

Uitgebreid tekentype (wchar_t)

Het type wchar_t is ontworpen om te werken met een set tekens waarvoor 1 byte niet voldoende is om bijvoorbeeld Unicode te coderen. De omvang van dit type is implementatieafhankelijk; in de regel komt het overeen met het type kort. Tekenreeksconstanten van het type wchar_t worden geschreven met het voorvoegsel L, bijvoorbeeld L»Gates».

Booleaans type (bool)

Booleaanse waarden kunnen alleen de waarden waar en onwaar aannemen, dit zijn gereserveerde woorden. De interne vorm voor het weergeven van de waarde false is 0 (nul). Elke andere waarde wordt als waar geïnterpreteerd. Wanneer geconverteerd naar een geheel getaltype, heeft true de waarde 1.

Drijvende-kommatypes (float, double en long double)

De C++-standaard definieert drie gegevenstypen voor het opslaan van reële waarden: float, double en long double.

Gegevenstypen met drijvende komma worden anders in het computergeheugen opgeslagen dan gegevenstypen met gehele getallen. De interne weergave van een reëel getal bestaat uit twee delen: de mantisse en de exponent. Op IBM PC-compatibele computers beslaan float-waarden 4 bytes, waarvan één binair cijfer is toegewezen voor het mantisse-teken, 8 bits voor de exponent en 23 voor de mantisse. De mantisse is een getal groter dan 1,0 maar kleiner dan 2,0. Omdat het eerste cijfer van de mantisse altijd 1 is, wordt dit niet opgeslagen.

Voor dubbele waarden die 8 bytes bezetten, worden respectievelijk 11 en 52 bits toegewezen voor de exponent en mantisse. De lengte van de mantisse bepaalt de nauwkeurigheid van het getal, en de lengte van de exponent bepaalt het bereik ervan. Zoals je kunt zien in de tabel aan het einde van het item, met hetzelfde aantal bytes toegewezen aan float- en long int-waarden, lopen de bereiken van hun toegestane waarden sterk uiteen vanwege de interne representatievorm.

De lange specificatie vóór een dubbele typenaam geeft aan dat er 10 bytes zijn toegewezen voor de waarde ervan.

Drijvende-kommaconstanten zijn standaard van het dubbele type. U kunt het type van een constante expliciet specificeren met behulp van de achtervoegsels F, f (zwevend) en L, l (lang). De constante 2E+6L zal bijvoorbeeld van het type long double zijn, en de constante 1.82f zal van het type float zijn.

Om programma's te schrijven die overdraagbaar zijn tussen platforms, kun je geen aannames doen over de grootte van het int-type. Om dit te verkrijgen, moet u de grootte van de bewerking gebruiken, waarvan het resultaat de grootte van het type in bytes is. Voor het MS-DOS-besturingssysteem zal sizeof (int) bijvoorbeeld resulteren in 2, maar voor Windows 98 of OS/2 zal het resultaat 4 zijn.

De ANSI-standaard specificeert geen waardebereiken voor basistypen; de relaties tussen hun groottes zijn bijvoorbeeld gedefinieerd:

sizeof(float) ≤ slzeof(dubbel) ≤ sizeof(lang dubbel)
sizeof(char) ≤ slzeof(kort) ≤ sizeof(int) ≤ sizeof(lang)

Opmerking

De minimaal en maximaal toegestane waarden voor integer-typen zijn implementatieafhankelijk en worden gegeven in het headerbestand (), kenmerken van echte typen - in het bestand (), evenals in de klassensjabloon numeriek_limits

typ leegte

Naast de genoemde typen omvatten de hoofdtypen van de taal het void-type, maar de reeks waarden van dit type is leeg. Het wordt gebruikt om functies te definiëren die geen waarde retourneren, om een ​​lege lijst met functieargumenten op te geven, als het basistype voor pointers, en bij typecast-bewerkingen.

Waardebereiken van eenvoudige gegevenstypen in C++ voor IBM PC-compatibele computers

Q: Wat betekent de term IBM PC-compatibele computer?
A: Een IBM PC-compatibele computer is een computer die qua architectuur dicht bij de IBM PC, XT en AT ligt. IBM PC-compatibele computers zijn gebouwd op microprocessors die compatibel zijn met de Intel 8086 (en, zoals u weet, zijn alle latere Intel-processors volledig achterwaarts compatibel met de 8086). In feite zijn dit bijna allemaal moderne computers.

Er zijn verschillende soorten gehele en reële typen geïntroduceerd, die verschillen in het bereik en de nauwkeurigheid van de gegevensrepresentatie, om de programmeur de kans te geven de mogelijkheden van specifieke apparatuur zo effectief mogelijk te gebruiken, aangezien de snelheid van berekeningen en de hoeveelheid geheugen afhankelijk zijn van de keuze van het type. Maar een programma dat voor één type computer is geoptimaliseerd, is mogelijk niet overdraagbaar naar andere platforms, dus in het algemeen moet u vermijden te vertrouwen op specifieke kenmerken van gegevenstypen.

Type Bereik van waarden Grootte (byte)
bool waar en onwaar 1
ondertekende char -128 … 127 1
niet-ondertekend teken 0 … 255 1
gesigneerd korte int -32 768 … 32 767 2
niet-ondertekende korte int 0 … 65 535 2
gesigneerd lange int -2 147 483 648 … 2 147 483 647 4
niet-ondertekend lange int 0 … 4 294 967 295 4
vlot 3.4e-38 … 3.4e+38 4
dubbele 1.7e-308 … 1.7C+308 8
lange dubbele 3,4e-4932 … 3,4e+4932 10

Voor reële typen toont de tabel de absolute waarden van de minimum- en maximumwaarden.

In deze sectie worden de belangrijkste gegevenstypen in C++ besproken; deze gegevenstypen worden ook wel ingebouwd genoemd. De programmeertaal C++ is een uitbreidbare programmeertaal. De term uitbreidbaar betekent dat u naast de ingebouwde gegevenstypen uw eigen gegevenstypen kunt maken. Daarom zijn er een groot aantal gegevenstypen in C++. We zullen alleen de belangrijkste bestuderen.

Tabel 1 - C++-gegevenstypen
Type byte Bereik van geaccepteerde waarden

gegevenstype geheel getal (Booleaans).

bool 1 0 / 255

gegevenstype geheel getal (teken).

verkoold 1 0 / 255

gehele gegevenstypen

korte int 2 -32 768 / 32 767
niet-ondertekende korte int 2 0 / 65 535
int 4
niet ondertekend int 4 0 / 4 294 967 295
lang int 4 -2 147 483 648 / 2 147 483 647
niet-ondertekend lange int 4 0 / 4 294 967 295

gegevenstypen met drijvende komma

vlot 4 -2 147 483 648.0 / 2 147 483 647.0
lange vlotter 8
dubbele 8 -9 223 372 036 854 775 808 .0 / 9 223 372 036 854 775 807.0

Tabel 1 toont de belangrijkste gegevenstypen in C++. De gehele tabel is verdeeld in drie kolommen. De eerste kolom geeft een gereserveerd woord aan, dat ieder zijn eigen gegevenstype zal bepalen. De tweede kolom geeft het aantal bytes aan dat is toegewezen aan een variabele met het bijbehorende gegevenstype. De derde kolom toont het bereik van aanvaardbare waarden. Houd er rekening mee dat in de tabel alle gegevenstypen zijn gerangschikt van klein naar groot.

bool-gegevenstype

De eerste in de tabel is het bool-gegevenstype een gegevenstype met gehele getallen, aangezien het bereik van geldige waarden gehele getallen van 0 tot 255 is. Maar zoals je al hebt opgemerkt, staat er tussen haakjes het gegevenstype Booleaans, en dit is ook waar. Omdat bool uitsluitend gebruikt om de resultaten van Booleaanse expressies op te slaan. Een Booleaanse expressie kan twee resultaten opleveren: waar of onwaar. waar - als de logische expressie waar is, onwaar - als de logische expressie onwaar is.

Maar aangezien het bereik van geldige waarden van het bool-gegevenstype van 0 tot 255 ligt, was het nodig om dit bereik op de een of andere manier te matchen met de logische constanten waar en onwaar gedefinieerd in de programmeertaal. De constante true is dus equivalent aan alle getallen van 1 tot en met 255, terwijl de constante false equivalent is aan slechts één geheel getal - 0. Beschouw een programma dat het gegevenstype bool gebruikt.

// data_type.cpp: definieert het toegangspunt voor de consoletoepassing. #include "stdafx.h" #include naamruimte std gebruiken; int main(int argc, char* argv) ( bool boolean = 25; // variabele van het type bool genaamd boolean if (boolean) // voorwaarde van de if cout-operator<< "true = " << boolean << endl; // выполнится в случае истинности условия else cout << "false = " << boolean << endl; // выполнится в случае, если условие ложно system("pause"); return 0; }

IN lijn 9typevariabele gedeclareerd bool , die is geïnitialiseerd op 25. Theoretisch daarnalijnen 9, in een Booleaanse variabele zou het getal 25 moeten bevatten, maar in feite bevat deze variabele het getal 1. Zoals ik al zei, het getal 0 is een valse waarde, het getal 1 is een echte waarde. Het punt is dat in een variabele als bool kan twee waarden bevatten: 0 (onwaar) of 1 (waar). Terwijl onder gegevenstype bool er wordt een hele byte toegewezen, wat betekent dat er een variabele van het type is bool kan getallen van 0 tot 255 bevatten. Om valse en echte waarden te bepalen zijn slechts twee waarden 0 en 1 nodig. De vraag rijst: “Waar zijn de andere 253 waarden voor?”

Op basis van deze situatie hebben we afgesproken om de getallen 2 tot en met 255 te gebruiken als het equivalent van het getal 1, dat wil zeggen de waarheid. Dit is precies de reden waarom de Booleaanse variabele het getal 25 bevat en niet 1. In lijnen 10 -13 gedeclareerd, waardoor de controle wordt overgedragen aan de exploitant lijn 11, als de voorwaarde waar is, en de operator in lijn 13, als de voorwaarde onwaar is. Het resultaat van het programma wordt weergegeven in Figuur 1.

Waar = 1 Druk op een willekeurige toets om door te gaan. . .

Figuur 1 - bool-gegevenstype

Gegevenstype char

Het char-gegevenstype is een geheel getal-gegevenstype dat wordt gebruikt om tekens weer te geven. Dat wil zeggen, elk teken komt overeen met een bepaald getal uit het bereik. Het gegevenstype char wordt ook wel het tekengegevenstype genoemd, omdat de grafische weergave van tekens in C++ mogelijk is dankzij char. Om tekens in C++ weer te geven, wordt aan het char-gegevenstype één byte toegewezen, één byte bevat 8 bits, vervolgens verheffen we twee tot de macht 8 en krijgen de waarde 256 - het aantal tekens dat kan worden gecodeerd. Met het char-gegevenstype kunt u dus elk van de 256 tekens weergeven. Alle gecodeerde tekens worden weergegeven in .

ASCII (van Engelse standaardcode voor informatie-uitwisseling) - Amerikaanse standaardcode voor informatie-uitwisseling.

Overweeg een programma dat het gegevenstype char gebruikt.

//symbols.cpp: Definieert het toegangspunt voor de consoletoepassing. #include "stdafx.h" #include naamruimte std gebruiken; int main(int argc, char* argv) ( char symbol = "a"; // een variabele van het type char declareren en initialiseren met het symbool "a" cout<< "symbol = " << symbol << endl; // печать символа, содержащегося в переменной symbol char string = "сайт"; // объявление символьного массива (строки) cout << "string = " << string << endl; // печать строки system("pause"); return 0; }

Dus, binnen lijn 9een variabele genaamd symbool , krijgt deze de symboolwaarde toegewezen"A" ( ASCII-code). IN lijn 10 cout-operator drukt het teken af ​​dat in de variabele zit symbool IN lijn 11een stringarray met de naam snaar , en de grootte van de array wordt impliciet gespecificeerd. Een string wordt opgeslagen in een stringarray"website" . Houd er rekening mee dat toen we het symbool opsloegen in een variabele zoals verkoold , daarna plaatsen we na het gelijkteken enkele aanhalingstekens waarin we het symbool schreven. Bij het initialiseren van een stringarray met een bepaalde string worden dubbele aanhalingstekens geplaatst na het gelijkteken, waarin een bepaalde string wordt geschreven. Net als bij een normaal teken worden tekenreeksen uitgevoerd met behulp van de operator uit, lijn 12. Het resultaat van het programma wordt getoond in Figuur 2.

Symbool = een string = site Druk op een willekeurige toets om door te gaan. . .

Figuur 2 - char-gegevenstype

Gehele gegevenstypen

Gegevenstypen met gehele getallen worden gebruikt om getallen weer te geven. Er zijn er zes in Tabel 1: korte int, niet-ondertekende korte int, int, niet-ondertekende int, lange int, niet-ondertekende lange int . Ze hebben allemaal hun eigen geheugengrootte en bereik van geaccepteerde waarden. Afhankelijk van de compiler kan de grootte van het in beslag genomen geheugen en het bereik van geaccepteerde waarden variëren. In Tabel 1 worden alle bereiken van geaccepteerde waarden en groottes van bezet geheugen gebruikt voor de MVS2010-compiler. Bovendien zijn alle gegevenstypen in Tabel 1 gerangschikt in oplopende volgorde van de grootte van het bezette geheugen en het bereik van geaccepteerde waarden. Het bereik van geaccepteerde waarden hangt op de een of andere manier af van de grootte van het bezette geheugen. Dienovereenkomstig geldt: hoe groter de omvang van het bezette geheugen, hoe groter het bereik van geaccepteerde waarden. Ook verandert het bereik van geaccepteerde waarden als het gegevenstype wordt gedeclareerd met het niet-ondertekende voorvoegsel. Het niet-ondertekende voorvoegsel geeft aan dat het gegevenstype geen ondertekende waarden kan opslaan, en vervolgens wordt het bereik van positieve waarden verdubbeld, bijvoorbeeld de gegevenstypen short int en unsigned short int.

Voorvoegsels voor gegevenstypes van gehele getallen:

kort het voorvoegsel verkort het gegevenstype waarop het wordt toegepast door de grootte van het geheugen dat het in beslag neemt te verkleinen;

lang het voorvoegsel breidt het gegevenstype uit waarop het wordt toegepast door de omvang van het geheugen dat het in beslag neemt te vergroten;

unsigned: het voorvoegsel verdubbelt het bereik van positieve waarden, terwijl het bereik van negatieve waarden niet kan worden opgeslagen in dit gegevenstype.

In wezen hebben we dus één geheel getaltype dat gehele getallen vertegenwoordigt: het int-gegevenstype. Dankzij de voorvoegsels kort, lang, niet-ondertekend verschijnt er een bepaalde verscheidenheid aan int-gegevenstypen, die verschillen in de grootte van het in beslag genomen geheugen en (of) het bereik van geaccepteerde waarden.

Gegevenstypen met drijvende komma

Er zijn twee soorten drijvende-kommagegevens in C++: float en double. Gegevenstypen met drijvende komma zijn ontworpen om getallen met drijvende komma op te slaan. De gegevenstypen float en double kunnen zowel positieve als negatieve getallen met drijvende komma opslaan. Het float-datatype heeft een geheugenvoetafdruk die de helft is van die van het double-datatype, waardoor het bereik van geaccepteerde waarden ook kleiner is. Als het float-gegevenstype wordt gedeclareerd met het lange voorvoegsel, is het bereik van geaccepteerde waarden gelijk aan het bereik van geaccepteerde waarden van het dubbele gegevenstype. Kortom, drijvende-kommagegevenstypen zijn nodig om problemen met zeer nauwkeurige berekeningen op te lossen, bijvoorbeeld geldtransacties.

We hebben dus gekeken naar de belangrijkste punten met betrekking tot de belangrijkste gegevenstypen in C++. Het enige dat overblijft is om te laten zien waar al deze bereiken van geaccepteerde waarden en de omvang van het bezette geheugen vandaan komen. En hiervoor zullen we een programma ontwikkelen dat de belangrijkste kenmerken van alle hierboven besproken soorten gegevens berekent.

// data_types.cpp: definieert het toegangspunt voor de consoletoepassing. #include "stdafx.h" #include // I/O-manipulatiebibliotheek #include // headerbestand met wiskundige functies #include naamruimte std gebruiken; int main(int argc, char* argv) ( cout<< " data type " << "byte" << " " << " max value "<< endl // kolomkoppen <<"bool = " << sizeof(bool) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) - 1) << endl << "char = " << sizeof(char) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) - 1) << endl << "short int = " << sizeof(short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 - 1) - 1) << endl << "unsigned short int = " << sizeof(unsigned short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) - 1) << endl << "int = " << sizeof(int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 - 1) - 1) << endl << "unsigned int = " << sizeof(unsigned int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) - 1) << endl << "long int = " << sizeof(long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 - 1) - 1) << endl << "unsigned long int = " << sizeof(unsigned long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) - 1) << endl << "float = " << sizeof(float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 - 1) - 1) << endl << "double = " << sizeof(double) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 - 1) - 1) << endl; system("pause"); return 0; }

Dit programma is geplaatst zodat u de kenmerken van gegevenstypen in uw systeem kunt bekijken. Het is niet nodig om de code te begrijpen, omdat het programma controle-instructies gebruikt waar u waarschijnlijk nog niet bekend mee bent. Voor een oppervlakkige kennismaking met de programmacode zal ik hieronder enkele punten toelichten. Exploitant groottevan() Berekent het aantal bytes dat is toegewezen aan een gegevenstype of variabele. Functie pow(x,y) verheft de betekenis x tot de macht y , deze functie is beschikbaar vanuit het headerbestand . vaste en setprecision()-manipulatoren beschikbaar vanuit het headerbestand . De eerste is opgelost , geeft waarden in vaste vorm door aan de uitvoerstroom. Manipulator setprecision(n) geeft n weer decimalen. De maximale waarde van een bepaald gegevenstype wordt berekend met behulp van de volgende formule:

Max_val_type = 2^(b * 8 - 1) - 1; // voor gegevenstypen met negatieve en positieve getallen // waarbij b het aantal bytes is dat in het geheugen is toegewezen voor een variabele met dit gegevenstype // vermenigvuldigen met 8, aangezien er 8 bits in één byte zitten // trek 1 af tussen haakjes, omdat de bereiknummers in tweeën moeten worden gedeeld voor positieve en negatieve waarden // trek aan het einde 1 af, omdat het bereik van getallen begint bij nul // gegevenstypen met het voorvoegsel unsigned max_val_type = 2^(b * 8) - 1; // alleen voor gegevenstypen met positieve getallen // de verklaringen voor de formule zijn vergelijkbaar, alleen de eenheid wordt niet van het haakje afgetrokken

Een voorbeeld van hoe het programma werkt kunt u zien in Figuur 3. De eerste kolom toont de belangrijkste gegevenstypen in C++, de tweede kolom toont de grootte van het geheugen dat voor elk gegevenstype is toegewezen, en de derde kolom toont de maximale waarde die de overeenkomstige gegevenstypes bevatten. gegevenstype kan bevatten. De minimumwaarde blijkt vergelijkbaar te zijn met het maximum. Voor gegevenstypen met het niet-ondertekende voorvoegsel is de minimumwaarde 0.

Gegevenstype byte maximale waarde bool = 1 255.00 char = 1 255.00 short int = 2 32767.00 unsigned short int = 2 65535.00 int = 4 2147483647.00 unsigned int = 4 4294967295.00 long int = 4 2147483647.0 0 niet-ondertekende lange int = 4 4294967295.00 float = 4 2147483647.00 dubbel = 8 9223372036854775808.00 Druk op een willekeurige toets om door te gaan. . .

Figuur 3 - C++-gegevenstypen

Als bijvoorbeeld aan een variabele van het type short int de waarde 33000 wordt toegewezen, zal het bitraster overlopen, aangezien de maximale waarde in een variabele van het type short int 32767 is. Dat wil zeggen dat er een andere waarde in een variabele wordt opgeslagen. van het type short int, zal deze hoogstwaarschijnlijk negatief zijn. Omdat we het gegevenstype int hebben besproken, is het de moeite waard om op te merken dat u het trefwoord int kunt weglaten en bijvoorbeeld gewoon kort kunt schrijven. De compiler interpreteert zo'n invoer als short int. Hetzelfde geldt voor de voorvoegsels die lang en niet ondertekend zijn. Bijvoorbeeld:

// afkorting voor gegevenstype int short a1; // hetzelfde als kort int lang a1; // hetzelfde als long int unsigned a1; // hetzelfde als unsigned int unsigned short a1; // hetzelfde als niet-ondertekende korte int

Programmeur zegt:

Hallo! Ik heb je artikel gelezen. Ik was heel verdrietig en grappig tegelijk. Vooral deze zin van jou is moordend: “Aangezien een variabele van het type char vaak als array wordt gebruikt, wordt het aantal mogelijke waarden bepaald.” 😆 😆 😆
Ik lach je niet uit. Een website maken is echt een prestatie. Ik wil u alleen met advies ondersteunen en u op een paar fouten wijzen.

1. De waarde van een variabele van het type char wordt als volgt toegewezen:

Hier is het:

Char a = *"A";

De pointer naar de array wordt gedeadresseerd en als resultaat wordt de waarde van het eerste element van de array geretourneerd, d.w.z. 'A'

2. Het resetten gaat als volgt:

Char a = NULL;
teken b = ();

//En zo wordt de regel in de hoofdtekst van het programma gewist

"" - dit symbool wordt een nulterminator genoemd. Het wordt aan het einde van de regel geplaatst. Je hebt zelf, zonder het te weten, de s1-array uit je artikel gevuld met dit symbool. Maar het was mogelijk om dit symbool alleen aan het nulelement van de array toe te wijzen.

3. Voel je vrij om terminologie te gebruiken.
Het =-teken is een toewijzingsbewerking.
Het *-teken is een de-adresseringsbewerking.
Ik bedoel dit fragment van het artikel: “Alles bleek zo eenvoudig, vóór het =-teken moest je een *-teken plaatsen en moest je het elementnummer opgeven (nul komt overeen met de eerste)”

Begrijp me niet verkeerd, het artikel kan niet bestaan ​​in zijn huidige vorm. Wees niet lui, herschrijf het.
Je hebt een grote verantwoordelijkheid! Ik meen het. De pagina's van uw site zijn opgenomen in de eerste pagina met Yandex-resultaten. Veel mensen zijn al begonnen uw fouten te herhalen.

Succes! Je kunt het!

:
Ik weet dit al heel lang, het is gewoon moeilijk om voortdurend 200 artikelen te herlezen om iets te corrigeren. En sommige onbeschofte types schrijven zo dat ze, zelfs als ze weten wat het beste is om te corrigeren, helemaal niet bereid zijn om het te corrigeren.

Andere fouten corrigeer ik graag. corrigeer eventuele onnauwkeurigheden als deze voorkomen. Ik waardeer je hulp. bedankt. Ik weet dit al heel lang, het is gewoon moeilijk om 200 artikelen voortdurend opnieuw te lezen om iets te corrigeren. En sommige onbeschofte types schrijven zo dat ze, zelfs als ze weten wat het beste is om te corrigeren, helemaal niet bereid zijn om het te corrigeren.
Met je char b = (); Dit is helemaal geen nulstelling. Ze zouden het op zijn minst moeten onderzoeken.
als we het hebben over het nulteken "" ; Toen ik de regel ermee vulde, wist ik heel goed dat het doel was om echte reiniging te laten zien, en niet iets dat zichtbaar is voor het oog, omdat de regel rommel bevat, die soms in de weg zit. Je moet zelf voorzichtiger zijn met de termen, "null-beëindigingssymbool" of gewoon "nul-symbool", geen terminator))) En het terminator-symbool klinkt gewoon cool.

Ik zal het artikel moderniseren, maar ik zal niet overstappen naar de stijl van iemand anders. Als ik denk dat het voor een beginner gemakkelijker is om het op deze manier te begrijpen dan op de manier die hij of zij wil, dan laat ik het zo. Begrijp mij ook niet verkeerd. Het woord ‘teken’ is voor een zwakke beginner veel gemakkelijker te begrijpen en te onthouden dan de definitie en naam van elk teken. Er is helemaal geen sprake van een vergissing, het is een teken, een teken. Minder nadruk op het ene geeft meer nadruk op het andere.

Andere fouten corrigeer ik graag. corrigeer eventuele onnauwkeurigheden als deze voorkomen. Ik waardeer je hulp. Bedankt.

Hallo nogmaals!
Ik wil het verduidelijken. De term “zero-terminator” (terminator van de Engelse limiter) werd gebruikt door mijn leraar aan de universiteit. Blijkbaar is dit ouderwets!
Wat betreft het opnieuw instellen van rijen.
teken b = (); Dit is echt een reset. De hele array is gevuld met nullen. Als je me niet gelooft, kijk dan eens!
Als we een regel in zijn natuurlijke, alledaagse betekenis beschouwen, dan is een ‘lege’ regel een regel waarin geen enkel teken voorkomt. Daarom is het in 99,9% van de gevallen voldoende om een ​​nulteken aan het begin te plaatsen. Normaal gesproken wordt een string verwerkt tot aan het eerste nulteken, en welke tekens erna komen is niet langer belangrijk. Ik begrijp dat je de lijn wilde resetten. Ik heb zojuist besloten een beproefde klassieke optie aan te bieden.

:
Wanneer "Gewoonlijk de tekenreeksverwerking tot aan het eerste null-teken gaat en welke tekens daarna komen, is het niet langer belangrijk" - ja, de tekenreeks wordt null gemaakt
Als we kijken naar "echte nulstelling van alle cellen van een rij (waarover ik schreef)" - nee, geen nulstelling, en zelfs het eerste teken is niet nul. Ik heb deze optie aangevinkt. MinGW(CodeBlock) - de hele array geeft het teken "a"
Ik denk niet dat dit een reden tot discussie is.

Een belangrijk verschil tussen de SI-taal en andere talen (PL1, FORTRAN, enz.) is de afwezigheid van een standaardprincipe, wat leidt tot de noodzaak om alle variabelen die in het programma worden gebruikt expliciet te declareren, samen met een indicatie van hun overeenkomstige typen .

Variabeledeclaraties hebben het volgende formaat:

[geheugenklasse-specificatie] type-specificatie descriptor [=initiator] [,descriptor [= initiator] ]...

Een descriptor is een identificatie voor een eenvoudige variabele of een complexer construct met vierkante haken, haakjes of een asterisk (een reeks sterretjes).

Een typespecificatie is een of meer trefwoorden die het type definiëren van de variabele die wordt gedeclareerd. De SI-taal kent een standaardset aan datatypen, waarmee je nieuwe (unieke) datatypen kunt construeren.

Initiator - specificeert de initiële waarde of lijst met initiële waarden die aan de variabele worden toegewezen wanneer deze wordt gedeclareerd.

Geheugenklassespecificatie - gedefinieerd door een van de vier SI-sleutelwoorden: auto, extern, register, statisch, en geeft aan hoe geheugen wordt toegewezen aan de gedeclareerde variabele enerzijds, en anderzijds de reikwijdte van deze variabele, dat wil zeggen, vanuit welke delen van het programma het toegankelijk is.

1.2.1 Categorieën van gegevenstypen

Trefwoorden om basisgegevenstypen te definiëren

Integer-typen: Float-typen: char float int dubbel kort lang dubbel lang ondertekend niet-ondertekend

Een variabele van elk type kan onveranderbaar worden verklaard. Dit wordt bereikt door het trefwoord const toe te voegen aan de typespecificatie. Objecten met het type const vertegenwoordigen alleen-lezen gegevens, d.w.z. aan deze variabele kan geen nieuwe waarde worden toegekend. Merk op dat als er geen typeaanduiding na het woord const staat, de typeaanduiding int wordt geïmpliceerd. Als het sleutelwoord const vóór de declaratie van samengestelde typen (array, structuur, mengsel, opsomming) komt, leidt dit ertoe dat elk element ook niet te wijzigen moet zijn, d.w.z. er kan slechts één keer een waarde aan worden toegekend.

Const dubbel A=2.128E-2;

const B=286; (const int B=286 is impliciet)

Voorbeelden van het declareren van samengestelde gegevens worden hieronder besproken.

Om gegevens van het type geheel getal te definiëren, worden verschillende trefwoorden gebruikt, die het bereik van waarden en de grootte van het geheugengebied bepalen dat is toegewezen aan variabelen (tabel 6).

Tabel 6

Houd er rekening mee dat de ondertekende en niet-ondertekende trefwoorden optioneel zijn. Ze geven aan hoe de nulbit van de gedeclareerde variabele wordt geïnterpreteerd, dat wil zeggen: als het sleutelwoord zonder teken is opgegeven, wordt de nulbit geïnterpreteerd als onderdeel van een getal, en anders wordt de nulbit geïnterpreteerd als ondertekend. Als het niet-ondertekende sleutelwoord ontbreekt, wordt de integer-variabele als ondertekend beschouwd. Als de typeaanduiding bestaat uit een sleuteltype met of zonder handtekening gevolgd door een variabele-identificatie, dan wordt deze behandeld als een variabele van het type int. Bijvoorbeeld:

Niet-ondertekend int n;

niet-ondertekend int b;

int c; (ondertekend int c is impliciet);

niet-ondertekend d; (impliceert niet-ondertekende int d);

ondertekend f; (ondertekend int f is impliciet).

Merk op dat de char type-modifier wordt gebruikt om een ​​karakter weer te geven (uit een array-representatie van karakters) of om letterlijke tekenreeksen te declareren. De waarde van een char-object is de code van 1 byte die overeenkomt met het teken dat het vertegenwoordigt. Om karakters van het Russische alfabet weer te geven, is de modifier voor het gegevensidentificatietype niet-ondertekende char, aangezien de codes van Russische letters de waarde van 127 overschrijden.

niet-ondertekend d; (impliceert niet-ondertekende int d);

De volgende opmerking moet worden gemaakt: de SI-taal definieert niet de geheugenrepresentatie en het bereik van waarden voor identificatoren met de int en unsigned int type modifiers. De grootte van het geheugen voor een variabele met de ondertekende int-type modifier wordt bepaald door de lengte van het machinewoord, dat op verschillende machines een andere grootte heeft. Op 16-bits machines is de woordgrootte dus 2 bytes, op 32-bits machines 4 bytes, d.w.z. het int-type is gelijk aan het korte int- of lange int-type, afhankelijk van de architectuur van de gebruikte pc. Hetzelfde programma kan dus correct werken op de ene computer en verkeerd op een andere. Om de lengte van het geheugen te bepalen dat door een variabele wordt ingenomen, kunt u de SI-taal sizeof-operator gebruiken, die de lengte van de opgegeven type-modifier retourneert.

1.2.3. Zwevende gegevens

Voor variabelen die een getal met drijvende komma vertegenwoordigen, worden de volgende typemodificatoren gebruikt: float, double, long double (in sommige implementaties van de lange dubbele taal is er geen SI).

Een waarde met de float-type modifier neemt 4 bytes in beslag. Hiervan wordt 1 byte toegewezen voor het teken, 8 bits voor de overtollige exponent en 23 bits voor de mantisse. Merk op dat het meest significante bit van de mantisse altijd 1 is, dus deze is niet gevuld, dus het bereik van waarden voor een drijvende-kommavariabele is ongeveer 3,14E-38 tot 3,14E+38.

Een dubbele waarde neemt 8 bits geheugen in beslag. Het formaat is vergelijkbaar met het float-formaat. De geheugenbits zijn als volgt verdeeld: 1 bit voor het teken, 11 bits voor de exponent en 52 bits voor de mantisse. Rekening houdend met het weggelaten hoge deel van de mantisse, loopt het bereik van waarden van 1,7E-308 tot 1,7E+308.

Zweven f, a, b;

dubbel x,y;

1.2.4. Wegwijzers

Een pointer is het adres van het geheugen dat is toegewezen om een ​​identificatie te huisvesten (de identificatie kan de naam zijn van een variabele, array, structuur of letterlijke tekenreeks). Als een variabele als pointer wordt gedeclareerd, bevat deze een geheugenadres waar een scalaire waarde van welk type dan ook kan worden gevonden. Wanneer u een variabele van het type pointer declareert, moet u het type gegevensobject opgeven waarvan het adres de variabele zal bevatten, en de naam van de pointer, voorafgegaan door een asterisk (of een groep sterretjes). Pointer-declaratieformaat:

type-specificatie [ modifier ] * specificatie.

De trefwoorden const, near, far, huge kunnen worden gebruikt als modifiers bij het declareren van een pointer. Het const trefwoord geeft aan dat de pointer niet kan worden gewijzigd in het programma. De grootte van een variabele die als pointer wordt gedeclareerd, hangt af van de computerarchitectuur en van het geheugenmodel dat wordt gebruikt waarvoor het programma wordt gecompileerd. Pointers naar verschillende gegevenstypen hoeven niet dezelfde lengte te hebben.

Om de grootte van de aanwijzer te wijzigen, kunt u de trefwoorden dichtbij, veraf, enorm gebruiken.

Niet-ondertekend int * a; /* variabele a is een verwijzing naar het typen van niet-ondertekende int */ double * x; /* variabele x geeft drijvende-kommagegevenstype met dubbele precisie aan */ char * fuffer ; /* declareer een pointer genaamd fuffer die verwijst naar een variabele van het type char */ double nomer;

ongeldig *adressen;

adressen = &nomer;

(dubbel *)adres++;

/* De adresvariabele wordt gedeclareerd als een verwijzing naar een object van welk type dan ook.

Daarom kan er het adres van elk object aan worden toegewezen (& is de bewerking voor het berekenen van het adres). Zoals hierboven opgemerkt, kan er echter geen rekenkundige bewerking op een aanwijzer worden uitgevoerd, tenzij het type gegevens waarnaar deze verwijst expliciet is bepaald. Dit kan worden gedaan door een cast-bewerking (dubbel *) te gebruiken om adressen om te zetten in een pointer om dubbel te typen, en vervolgens het adres te verhogen. */ const * dr;

/* De dr-variabele wordt gedeclareerd als een verwijzing naar een constante expressie, d.w.z. De waarde van een pointer kan tijdens de uitvoering van het programma veranderen, maar de waarde waarnaar deze verwijst niet. */ niet-ondertekende char * const w = &obj.

Een variabele van het opsommingstype kan de waarde aannemen van een van de genoemde constanten in de lijst. Benoemde lijstconstanten zijn van het type int. Het geheugen dat correspondeert met een opsommingsvariabele is dus het geheugen dat nodig is om een ​​int-waarde te huisvesten.

Variabelen van het type enum kunnen worden gebruikt in indexexpressies en als operanden in rekenkundige en relationele bewerkingen.

In het eerste formaat 1 worden opsommingsnamen en -waarden gespecificeerd in een opsommingslijst. De optionele opsommingstagnaam is een ID die de opsommingstag benoemt die is gedefinieerd door de opsommingslijst. De descriptor noemt een opsommingsvariabele. In een declaratie kan meer dan één variabele van het opsommingstype worden opgegeven.

Een opsommingslijst bevat een of meer constructies van de vorm:

identificatie [= constante expressie]

Elke identifier benoemt een element van de opsomming. Alle ID's in de enum-lijst moeten uniek zijn. Als er geen constante uitdrukking is, komt de eerste identificatie overeen met de waarde 0, de volgende identificatie met de waarde 1, enz. De naam van een opsommingsconstante is gelijk aan de waarde ervan.

Een identificatie die aan een constante expressie is gekoppeld, neemt de waarde aan die door die constante expressie is opgegeven. De constante expressie moet van het type int zijn en kan positief of negatief zijn. Aan de volgende identificatie in de lijst wordt de waarde van de constante uitdrukking plus 1 toegewezen als die identificatie geen eigen constante uitdrukking heeft. Het gebruik van opsommingselementen moet aan de volgende regels voldoen:

1. De variabele kan dubbele waarden bevatten.

2. Identifiers in een opsommingslijst moeten onderscheiden zijn van alle andere identifiers in hetzelfde bereik, inclusief namen van reguliere variabelen en identifiers uit andere opsommingslijsten.

3. Namen van enumtypen moeten onderscheiden zijn van andere namen van enumtypen, structuren en mengsels in hetzelfde bereik.

4. De waarde kan na het laatste element van de opsommingslijst komen.

Enum week ( SUB = 0, /* 0 */ VOS = 0, /* 0 */ VIJVER, /* 1 */ VTOR, /* 2 */ SRED, /* 3 */ HETV, /* 4 */ PJAT /* 5 */ ) rab_ned ;

In dit voorbeeld wordt een opsombare tagweek gedeclareerd, met een corresponderende set waarden, en wordt een variabele rab_ned gedeclareerd van het type week.

Het tweede formaat gebruikt de naam van een opsommingstag om te verwijzen naar een opsommingstype dat ergens anders is gedefinieerd. De naam van de opsommingstag moet verwijzen naar een reeds gedefinieerde opsommingstag binnen het huidige bereik. Omdat de opsommingstag ergens anders wordt gedeclareerd, wordt de opsommingslijst niet weergegeven in de declaratie.

Bij het declareren van een verwijzing naar een opsommingsgegevenstype en het declareren van typedefs voor opsommingstypen, kunt u de naam van een opsommingstag gebruiken voordat die opsommingstag wordt gedefinieerd. De enum-definitie moet echter voorafgaan aan elk gebruik van de pointer van de typedef-declaratie naar het type. Een declaratie zonder een daaropvolgende lijst met descriptoren beschrijft een tag, of, om zo te zeggen, een opsommingspatroon.

1.2.6. Arrays

Arrays zijn een groep elementen van hetzelfde type (double, float, int, etc.). Uit de array-declaratie moet de compiler informatie verkrijgen over het type array-elementen en hun aantal. Een arraydeclaratie heeft twee formaten:

type-specificatie descriptor [const - expressie];

type-specificatie descriptor;

De descriptor is de identificatie van de array.

De type-specificatie specificeert het type van de elementen van de gedeclareerde array. Array-elementen kunnen geen functies of lege elementen zijn.

De constante-uitdrukking tussen vierkante haakjes specificeert het aantal elementen in de array. Bij het declareren van een array kan in de volgende gevallen een constante expressie worden weggelaten:

Wanneer gedeclareerd, wordt de array geïnitialiseerd,

De array wordt gedeclareerd als een formele parameter van de functie,

SI definieert alleen eendimensionale arrays, maar aangezien een element van een array een array kan zijn, kunnen ook multidimensionale arrays worden gedefinieerd. Ze worden geformaliseerd door een lijst met constante-expressies na de array-ID, waarbij elke constante-expressie tussen zijn eigen vierkante haken staat.

Elke constante-expressie tussen vierkante haken specificeert het aantal elementen langs die dimensie van de array, zodat een tweedimensionale array-declaratie twee constante-expressies bevat, een driedimensionale array drie, enzovoort. Merk op dat in SI het eerste element van een array een index van 0 heeft.

Int een; /* weergegeven als een matrix a a a a a a */ dubbel b; /* vector van 10 elementen van het type double */ int w = ( ( 2, 3, 4 ), ( 3, 4, 8 ), ( 1, 0, 9 ) );

In het laatste voorbeeld wordt de array w gedeclareerd. Lijsten tussen accolades komen overeen met arrayreeksen; de initialisatie wordt niet correct uitgevoerd.

In de SI-taal kun je array-secties gebruiken, net als in andere talen op hoog niveau (PL1, enz.), Er worden echter een aantal beperkingen opgelegd aan het gebruik van secties. Secties worden gevormd door het weglaten van een of meer paren vierkante haken. Paren vierkante haakjes kunnen alleen van rechts naar links en strikt opeenvolgend worden neergezet. Secties van arrays worden gebruikt om het rekenproces te organiseren in SI-functies die door de gebruiker zijn ontwikkeld.

Als u s schrijft bij het aanroepen van een functie, wordt de nulreeks van de array s doorgegeven.

Wanneer je toegang krijgt tot een array b, kun je bijvoorbeeld b schrijven en een vector van vier elementen wordt overgedragen, en als je toegang krijgt tot b krijg je een tweedimensionale array van grootte 3 bij 4. Je kunt b niet schrijven, wat impliceert dat een vector dat wel zal doen worden overgedragen, omdat dit niet voldoet aan de beperking die wordt opgelegd aan het gebruik van array-secties.

Een voorbeeld van een karakterarraydeclaratie.

char str = "karakterarraydeclaratie";

Merk op dat er nog één element in een letterlijk teken zit, aangezien het laatste element de escape-reeks "\0" is.

1.2.7. Structuren

Structuren zijn samengestelde objecten die elementen van elk type bevatten, met uitzondering van functies. In tegenstelling tot een array, die een homogeen object is, kan een structuur heterogeen zijn. Het structuurtype wordt bepaald door een invoer van het formulier:

struct (definitielijst)

In de structuur moet minimaal één component worden gespecificeerd. De definitie van structuren is als volgt:

datatype-descriptor;

waarbij data-type het structuurtype specificeert voor de objecten die in de descriptoren zijn gedefinieerd. In hun eenvoudigste vorm zijn handvatten identificatiegegevens of arrays.

Structuur ( dubbel x,y; ) s1, s2, sm;

struct (int jaar; char moth, dag; ) date1, date2;

Variabelen s1, s2 worden gedefinieerd als structuren, die elk uit twee componenten x en y bestaan. De variabele sm wordt gedefinieerd als een array van negen structuren. Elk van de twee variabelen date1, date2 bestaat uit drie componenten jaar, mot, dag. >p>Er is een andere manier om een ​​naam aan een structuurtype te koppelen: deze is gebaseerd op het gebruik van een structuurtag. Een structuurtag is vergelijkbaar met een tag van het type enum. De structuurtag is als volgt gedefinieerd:

struct-tag (lijst met beschrijvingen;);

waarbij tag een identificatie is.

In onderstaand voorbeeld wordt de studentidentifier beschreven als structuurtag:

De structuurtag wordt gebruikt om structuren van dit type vervolgens in de vorm te declareren:

struct id-lijsttag;

struct studie st1,st2;

Het gebruik van structuurtags is noodzakelijk om recursieve structuren te beschrijven. Hieronder wordt het gebruik van recursieve structuurtags besproken.

Struct knooppunt ( int data; struct knooppunt * volgende; ) st1_node;

Het structuurtagknooppunt is inderdaad recursief omdat het in zijn eigen beschrijving wordt gebruikt, d.w.z. bij het formaliseren van de volgende pointer. Structuren kunnen niet direct recursief zijn, d.w.z. een knooppuntstructuur kan geen component bevatten die een knooppuntstructuur is, maar elke structuur kan een component hebben die verwijst naar het type ervan, zoals in het bovenstaande voorbeeld is gedaan.

U krijgt toegang tot structuurcomponenten door de structuurnaam op te geven en de volgende naam, gescheiden door een punt, van de geselecteerde component, bijvoorbeeld:

St1.naam = "Ivanov";

st2.id=st1.id;

st1_node.data=st1.leeftijd;

1.2.8. Combinaties (mengsels)

Een unie lijkt op een structuur, maar slechts één van de elementen van de unie kan op elk moment worden gebruikt (of met andere woorden, er kan op worden gereageerd). Het jointype kan als volgt worden opgegeven:

Union ( beschrijving van element 1; ... beschrijving van element n; );

Het belangrijkste kenmerk van een unie is dat hetzelfde geheugengebied wordt toegewezen voor elk van de gedeclareerde elementen, d.w.z. ze overlappen elkaar. Hoewel dit geheugengebied toegankelijk is met behulp van elk van de elementen, moet het element voor dit doel zo worden geselecteerd dat het verkregen resultaat niet betekenisloos is.

Leden van een vakbond worden op dezelfde manier benaderd als structuren. De union-tag kan op precies dezelfde manier worden geformaliseerd als de structuur-tag.

De vereniging wordt gebruikt voor de volgende doeleinden:

Initialiseren van een geheugenobject dat in gebruik is als op een gegeven moment slechts één van de vele objecten actief is;

Interpreteer de onderliggende representatie van een object van één type alsof aan dat object een ander type is toegewezen.

Wanneer u een infor-object van het type union gebruikt, kunt u alleen het element verwerken dat de waarde heeft ontvangen, d.w.z. Na het toekennen van een waarde aan het inform.fio-element heeft het geen zin om andere elementen te benaderen. De ua-aaneenschakeling maakt afzonderlijke toegang mogelijk tot de lage ua.al- en hoge ua.al-bytes van het twee-byte-nummer ua.ax .

1.2.9. Bitvelden

Een element van de structuur kan een bitveld zijn dat toegang biedt tot individuele geheugenbits. Bitvelden kunnen niet buiten structuren worden gedeclareerd. U kunt ook geen arrays van bitvelden organiseren en u kunt de adresbepalingsbewerking niet op de velden toepassen. Over het algemeen wordt het type structuur met een bitveld als volgt gespecificeerd:

Structuur (unsigned identifier 1: veldlengte 1; unsigned identifier 2: veldlengte 2; )

lengte - velden worden gespecificeerd door een geheel getal-expressie of constante. Deze constante specificeert het aantal bits dat aan het overeenkomstige veld is toegewezen. Een veld met lengte nul geeft de uitlijning met de volgende woordgrens aan.

Structuur ( niet-ondertekend a1: 1; niet-ondertekend a2: 2; niet-ondertekend a3: 5; niet-ondertekend a4: 2; ) prim;

Bitveldstructuren kunnen ook ondertekende componenten bevatten. Dergelijke componenten worden automatisch op de juiste woordgrenzen geplaatst, en sommige woordbits kunnen ongebruikt blijven.

1.2.10. Variabelen met veranderlijke structuur

Heel vaak behoren sommige programmaobjecten tot dezelfde klasse, waarbij ze slechts op enkele details verschillen. Denk bijvoorbeeld aan de weergave van geometrische vormen. Algemene informatie over vormen kan elementen omvatten zoals oppervlakte en omtrek. De overeenkomstige geometrische afmetingsinformatie kan echter afhankelijk van hun vorm verschillen.

Beschouw een voorbeeld waarin informatie over geometrische vormen wordt weergegeven op basis van het gecombineerde gebruik van structuur en vereniging.

Structuurfiguur ( dubbel gebied,omtrek; /* gemeenschappelijke componenten */ int type; /* componentattribuut */ union /* opsomming van componenten */ ( dubbele straal; /* cirkel */ dubbel a; /* rechthoek */ dubbel b ; /* driehoek */ ) geom_fig ) fig1, fig2;

Over het algemeen zal elk figuurobject uit drie componenten bestaan: oppervlakte, omtrek, type. De typecomponent wordt het actieve componentlabel genoemd omdat het wordt gebruikt om aan te geven welke component van de geom_fig unie momenteel actief is. Deze structuur wordt een variabele structuur genoemd omdat de componenten ervan veranderen afhankelijk van de waarde van het label van de actieve component (de waarde van type).

Merk op dat het raadzaam is om in plaats van een int-typecomponent een opgesomd type te gebruiken. Bijvoorbeeld zoals dit

Enum figuur_schaak (CIRKEL, DOOS, DRIEHOEK);

De constanten CIRCLE, BOX, TRIANGLE ontvangen waarden die respectievelijk gelijk zijn aan 0, 1, 2. De typevariabele kan worden gedeclareerd als een opgesomd type:

enum figuur_schaaktype;

In dit geval waarschuwt de SI-compiler de programmeur voor mogelijk foutieve toewijzingen, zoals

figuur.type = 40;

Over het algemeen bestaat een structuurvariabele uit drie delen: een set gemeenschappelijke componenten, een label voor de actieve component en een deel met veranderende componenten. De algemene vorm van een variabele structuur is als volgt:

Structure (gemeenschappelijke componenten; actief componentlabel; unie (componentbeschrijving 1; componentbeschrijving 2; ::: componentbeschrijving n; ) union-identifier; ) structuur-identifier;

Voorbeeld van het definiëren van een structuurvariabele met de naam helth_record

Structuur ( /* algemene informatie */ char naam ; /* naam */ int leeftijd; /* leeftijd */ char geslacht; /* geslacht */ /* actief componentlabel */ /* (burgerlijke staat) */ enum merital_status ins ; /* variabel deel */ unie ( /* single */ /* geen component */ struct ( /* getrouwd */ char echtgenoot_naam; int no_children; ) huwelijksinfo; /* gescheiden */ char date_divorced; ) huwelijksgegevens;

enum burgerlijke_status (SINGLE, /* single */ MARRIGO, /* getrouwd */ GESCHEIDEN /* gescheiden */ ) ;

U kunt via links toegang krijgen tot de componenten van de structuur:

Helth_record.neme, helth_record.ins, helth_record.marriage_info.marriage_date .

1.2.11. Objecten en typen definiëren

Zoals hierboven vermeld, moeten alle variabelen die in SI-programma's worden gebruikt, worden gedeclareerd. Het type variabele dat wordt gedeclareerd, hangt af van welk trefwoord wordt gebruikt als typespecificatie en of de specificatie een eenvoudige identificatie is of een combinatie van een identificatie met een aanwijzer (sterretje), array (vierkante haakjes) of functiemodificator (haakjes).

Laten we een belangrijk kenmerk van de SI-taal opmerken: bij het declareren kan meer dan één modifier tegelijkertijd worden gebruikt, wat het mogelijk maakt om veel verschillende complexe typedescriptors te creëren.

We moeten echter niet vergeten dat sommige combinaties van modificatoren onaanvaardbaar zijn:

Array-elementen kunnen geen functies zijn.

Functies kunnen geen matrices of functies retourneren.

Bij het initialiseren van complexe descriptoren hebben vierkante haken en haakjes (rechts van de identifier) ​​voorrang op het sterretje (links van de identifier). Vierkantjes of haakjes hebben dezelfde prioriteit en worden van links naar rechts uitgevouwen. Er wordt rekening gehouden met de typespecificatie in de laatste stap, wanneer de specificatie al volledig is geïnterpreteerd. U kunt haakjes gebruiken om de volgorde van interpretatie indien nodig te wijzigen.

Voor het interpreteren van complexe beschrijvingen wordt een eenvoudige regel voorgesteld die klinkt als "van binnenuit", en die uit vier stappen bestaat.

1. Begin met de identificatie en kijk naar rechts om te zien of er vierkantjes of haakjes staan.

2. Als dat zo is, interpreteer dan dit deel van de descriptor en kijk vervolgens naar links op zoek naar een asterisk.

3. Als er op enig moment aan de rechterkant een haakje sluiten wordt aangetroffen, moeten al deze regels binnen de haakjes eerst worden toegepast en daarna gaat de interpretatie verder.

4. Interpreteer de typeaanduiding.

Int * (*) comp ) ();

6 5 3 1 2 4

In dit voorbeeld wordt de variabele comp (1) gedeclareerd als een array van tien (2) pointers (3) naar functies (4) die pointers (5) retourneren naar gehele waarden (6).

Char * (* (*var) ()) ;

7 6 4 2 1 3 5

De variabele var (1) wordt gedeclareerd als een pointer (2) naar een functie (3) die een pointer (4) retourneert naar een array (5) van 10 elementen die pointers (6) zijn naar char-waarden.

Merk op dat elk type kan worden gedeclareerd met behulp van het sleutelwoord typedef, inclusief pointer-, functie- of array-typen. Een naam met het trefwoord typedef voor pointer-, structuur- en union-typen kan worden gedeclareerd voordat deze typen zijn gedefinieerd, maar binnen het bereik van de declarer.

Typedef double(*MATH)();

/* MATH - nieuwe typenaam die een verwijzing vertegenwoordigt naar een functie die dubbele waarden retourneert */ MATH cos;

/* cos verwijzing naar een functie die waarden retourneert van het type double */ /* Er kan een gelijkwaardige declaratie worden gedaan */ double (* cos)();

typedef char FIO /* FIO - array van veertig tekens */ FIO person;

/* De person-variabele is een array van veertig tekens */ /* Dit komt overeen met een declaratie */ char person;

Bij het declareren van variabelen en typen werden hier typenamen (MATH FIO) gebruikt. Bovendien kunnen typenamen in drie andere gevallen worden gebruikt: in de lijst met formele parameters, in functiedeclaraties, in type-casting-bewerkingen en in de omvang van de bewerking (type-casting-bewerking).

De typenamen voor basis-, opsommings-, structuur- en mengseltypen zijn de typespecificaties voor die typen. De typenamen voor array-aanwijzer- en functietypen worden als volgt gespecificeerd met behulp van abstracte descriptors:

abstract-descriptor-type-specificatie;

Een abstract-handler is een niet-identificerende handle die bestaat uit een of meer pointer-, array- of functiemodifiers. De pointer-modifier (*) wordt altijd vóór de identifier in de descriptor gegeven, en de array- en functiemodifiers () worden erna gegeven. Om een ​​abstracte descriptor correct te interpreteren, moet men de interpretatie dus beginnen met de impliciete identificatie.

Abstracte descriptoren kunnen complex zijn. De haakjes in complexe abstracte descriptoren specificeren de volgorde van interpretatie op een vergelijkbare manier als de interpretatie van complexe descriptoren in declaraties.

1.2.12. Initialisatie van gegevens

Wanneer een variabele wordt gedeclareerd, kan hieraan een initiële waarde worden toegewezen door een initiator aan een declarator toe te voegen. De initiator begint met het teken "= en heeft de volgende vormen.

Formaat 1: = initiatiefnemer;

Formaat 2: = (lijst - initiatiefnemers);

Formaat 1 wordt gebruikt bij het initialiseren van variabelen van basistypen en pointers, en formaat 2 wordt gebruikt bij het initialiseren van samengestelde objecten.

Een tweedimensionale array van b gehele waarden wordt geïnitialiseerd; array-elementen krijgen waarden uit de lijst toegewezen. Dezelfde initialisatie kan als volgt worden uitgevoerd:

statisch int b = ( ( 1,2 ), ( 3,4 ) );

Bij het initialiseren van een array kunt u een of meer dimensies weglaten

statisch int b)