Zoeken…


Initialisatie van variabelen in C

Bij gebrek aan expliciete initialisatie worden externe en static variabelen gegarandeerd op nul geïnitialiseerd; automatische variabelen (inclusief register ) hebben onbepaalde 1 (dwz afval) beginwaarden.

Scalaire variabelen kunnen worden geïnitialiseerd wanneer ze worden gedefinieerd door de naam te volgen met een is-gelijk-teken en een uitdrukking:

int x = 1;
char squota = '\'';
long day = 1000L * 60L * 60L * 24L; /* milliseconds/day */

Voor externe en static variabelen moet de initialisatie een constante expressie 2 zijn ; de initialisatie wordt eenmaal gedaan, conceptueel voordat het programma wordt uitgevoerd.

Voor automatische en register is de initialisatie niet beperkt tot een constante: het kan elke uitdrukking zijn die eerder gedefinieerde waarden bevat, zelfs functieaanroepen.

Zie bijvoorbeeld het codefragment hieronder

int binsearch(int x, int v[], int n)
{
   int low = 0;
   int high = n - 1;
   int mid;
   ...
}

in plaats van

   int low, high, mid;

   low = 0;
   high = n - 1;

De initialisatie van automatische variabelen is eigenlijk gewoon steno voor toewijzingsopdrachten. Welke vorm de voorkeur heeft, is grotendeels een kwestie van smaak. Over het algemeen gebruiken we expliciete opdrachten, omdat initializers in verklaringen moeilijker te zien zijn en verder weg van het gebruikspunt. Aan de andere kant moeten variabelen alleen worden gedeclareerd wanneer ze waar mogelijk worden gebruikt.

Een array initialiseren:

Een array kan worden geïnitialiseerd door de verklaring te volgen met een lijst met initialisatie tussen accolades en gescheiden door komma's.

Om bijvoorbeeld een array-dagen te initialiseren met het aantal dagen in elke maand:

int days_of_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }

(Merk op dat januari in deze structuur wordt gecodeerd als maand nul.)

Wanneer de grootte van de array wordt weggelaten, berekent de compiler de lengte door de initializers te tellen, waarvan er in dit geval 12 zijn.

Als er minder initializers voor een array zijn dan de opgegeven grootte, zijn de andere nul voor alle typen variabelen.

Het is een fout om te veel initializers te hebben. Er is geen standaardmanier om herhaling van een initialisatie te specificeren - maar GCC heeft een extensie om dit te doen.

C99

In C89 / C90 of eerdere versies van C was er geen manier om een element in het midden van een array te initialiseren zonder ook alle voorgaande waarden op te geven.

C99

Met C99 en hoger kunt u met aangewezen initializers willekeurige elementen van een array initialiseren, waarbij niet-geïnitialiseerde waarden als nullen worden achtergelaten.

Tekenreeksen initialiseren:

Tekenreeksen zijn een speciaal geval van initialisatie; een string kan worden gebruikt in plaats van de accolades en komma's:

char chr_array[] = "hello";

is een afkorting voor de langere maar equivalent:

char chr_array[] = { 'h', 'e', 'l', 'l', 'o', '\0' };

In dit geval is de arraygrootte zes (vijf tekens plus de afsluitende '\0' ).

1 Wat gebeurt er met een aangegeven, niet-geïnitialiseerde variabele in C? Heeft het een waarde?

2 Merk op dat een constante uitdrukking wordt gedefinieerd als iets dat kan worden geëvalueerd tijdens het compileren. Dus, int global_var = f(); is ongeldig. Een andere veel voorkomende misvatting is het beschouwen van een const gekwalificeerde variabele als een constante uitdrukking . In C betekent const "alleen-lezen", niet "compileer tijdconstante". Dus globale definities zoals const int SIZE = 10; int global_arr[SIZE]; en const int SIZE = 10; int global_var = SIZE; zijn niet legaal in C.

Structuren en structuren van structuren initialiseren

Structuren en arrays van structuren kunnen worden geïnitialiseerd door een reeks waarden tussen accolades, één waarde per lid van de structuur.

struct Date
{
    int year;
    int month;
    int day;
};

struct Date us_independence_day = { 1776, 7, 4 };

struct Date uk_battles[] =
{
    { 1066, 10, 14 },    // Battle of Hastings
    { 1815,  6, 18 },    // Battle of Waterloo
    { 1805, 10, 21 },    // Battle of Trafalgar
};

Merk op dat de initialisatie van de array zonder de interne accolades zou kunnen worden geschreven en in het verleden (voor bijvoorbeeld 1990) vaak zonder deze zou zijn geschreven:

struct Date uk_battles[] =
{
    1066, 10, 14,    // Battle of Hastings
    1815,  6, 18,    // Battle of Waterloo
    1805, 10, 21,    // Battle of Trafalgar
};

Hoewel dit werkt, is het niet een goede moderne stijl - je moet niet proberen deze notatie in nieuwe code te gebruiken en de compilerwaarschuwingen corrigeren die het meestal oplevert.

Zie ook aangewezen initializers .

Gebruik van aangewezen initializers

C99

C99 introduceerde het concept van aangewezen initializers. Hiermee kunt u opgeven welke elementen van een array, structuur of unie moeten worden geïnitialiseerd met de volgende waarden.

Aangewezen initializers voor array-elementen

Voor een eenvoudig type zoals gewoon int :

int array[] = { [4] = 29, [5] = 31, [17] = 101, [18] = 103, [19] = 107, [20] = 109 };

De term tussen vierkante haken, die elke constante geheel-getaluitdrukking kan zijn, geeft aan welk element van de array moet worden geïnitialiseerd door de waarde van de term na het = -teken. Niet-gespecificeerde elementen zijn standaard geïnitialiseerd, wat betekent dat er nullen zijn gedefinieerd. Het voorbeeld toont de aangewezen initializers in volgorde; ze hoeven niet in orde te zijn. Het voorbeeld toont hiaten; die zijn legitiem. Het voorbeeld toont niet twee verschillende initialisaties voor hetzelfde element; ook dat is toegestaan (ISO / IEC 9899: 2011, §6.7.9 Initialisatie, ¶19 De initialisatie vindt plaats in de volgorde van de initialisatielijst, waarbij elke initialisator een bepaald subobject vervangt dat een eerder vermelde initialisator voor hetzelfde subobject vervangt ).

In dit voorbeeld is de grootte van de array niet expliciet gedefinieerd, dus bepaalt de maximale index die is opgegeven in de aangewezen initializers de grootte van de array - wat in het voorbeeld 21 elementen zou zijn. Als de grootte was gedefinieerd, zou het initialiseren van een invoer voorbij het einde van de array zoals gewoonlijk een fout zijn.

Aangewezen initializers voor structuren

U kunt opgeven welke elementen van een structuur worden geïnitialiseerd met behulp van de . element notatie:

struct Date
{
    int year;
    int month;
    int day;
};

struct Date us_independence_day = { .day = 4, .month = 7, .year = 1776 };

Als elementen niet worden vermeld, worden ze standaard geïnitialiseerd (op nul gezet).

Aangewezen initialisator voor vakbonden

U kunt opgeven welk element van een unie wordt geïnitialiseerd met een aangewezen initialisatie.

C89

Voorafgaand aan de C-standaard was er geen manier om een union te initialiseren. Met de C89 / C90-standaard kunt u het eerste lid van een union initialiseren - dus de keuze welk lid het eerst wordt vermeld, is van belang.

struct discriminated_union
{
    enum { DU_INT, DU_DOUBLE } discriminant;
    union
    {
        int     du_int;
        double  du_double;
    } du;
};

struct discriminated_union du1 = { .discriminant = DU_INT, .du = { .du_int = 1 } };
struct discriminated_union du2 = { .discriminant = DU_DOUBLE, .du = { .du_double = 3.14159 } };
C11

Merk op dat je met C11 anonieme vakbondsleden in een structuur kunt gebruiken, zodat je de du name in het vorige voorbeeld niet nodig hebt:

struct discriminated_union
{
    enum { DU_INT, DU_DOUBLE } discriminant;
    union
    {
        int     du_int;
        double  du_double;
    };
};

struct discriminated_union du1 = { .discriminant = DU_INT, .du_int = 1 };
struct discriminated_union du2 = { .discriminant = DU_DOUBLE, .du_double = 3.14159 };

Aangewezen initializers voor arrays van structuren, enz

Deze constructies kunnen worden gecombineerd voor arrays van structuren die elementen bevatten die arrays zijn, enz. Het gebruik van volledige sets van accolades zorgt ervoor dat de notatie ondubbelzinnig is.

typedef struct Date Date;  // See earlier in this example

struct date_range
{
    Date    dr_from;
    Date    dr_to;
    char    dr_what[80];
};

struct date_range ranges[] =
{
    [3] = { .dr_from = { .year = 1066, .month = 10, .day = 14 },
            .dr_to   = { .year = 1066, .month = 12, .day = 25 },
            .dr_what = "Battle of Hastings to Coronation of William the Conqueror",
          },
    [2] = { .dr_from = { .month = 7, .day =  4, .year = 1776 },
            .dr_to   = { .month = 5, .day = 14, .year = 1787 },
            .dr_what = "US Declaration of Independence to Constitutional Convention",
          }
 };

Bereik opgeven in array-initializers

GCC biedt een extensie waarmee u een reeks elementen in een array kunt opgeven die dezelfde initialisatie moeten krijgen:

int array[] = { [3 ... 7] = 29, 19 = 107 };

De drievoudige punten moeten gescheiden zijn van de getallen, anders moet een van de punten worden geïnterpreteerd als onderdeel van een drijvend puntgetal ( maximale munch- regel).



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow