Sök…


Initialisering av variabler i C

I avsaknad av uttrycklig initialisering garanteras externa och static variabler att initialiseras till noll; automatiska variabler (inklusive register ) har obestämda 1 (dvs. sopor) initialvärden.

Scalära variabler kan initialiseras när de definieras genom att följa namnet med ett lika tecken och ett uttryck:

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

För externa och static variabler måste initialiseraren vara ett konstant uttryck 2 ; initialiseringen görs en gång, konceptuellt innan programmet börjar köras.

För automatiska och register är initialiseraren inte begränsad till att vara en konstant: det kan vara vilket uttryck som involverar tidigare definierade värden, även funktionssamtal.

Se till exempel kodavsnittet nedan

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

istället för

   int low, high, mid;

   low = 0;
   high = n - 1;

I själva verket är initialisering av automatiska variabler bara kortfattad för uppdragsuppdrag. Vilken form att föredra är till stor del en smakfråga. Vi använder i allmänhet uttryckliga uppdrag, eftersom initialiseringar i förklaringar är svårare att se och längre bort från användningsstället. Å andra sidan bör variabler endast deklareras när de ska användas när det är möjligt.

Initiera en matris:

En matris kan initialiseras genom att följa dess deklaration med en lista över initialiserare medföljande hängslen och separerade med komma-tecken.

För att till exempel initialisera en matrisdagar med antalet dagar i varje månad:

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

(Observera att januari är kodad som månad noll i denna struktur.)

När storleken på matrisen utelämnas beräknar kompilatorn längden genom att räkna initialisatorerna, av vilka det finns 12 i detta fall.

Om det finns färre initialiseringar för en matris än den angivna storleken kommer de andra att vara noll för alla typer av variabler.

Det är ett fel att ha för många initialiserare. Det finns inget standard sätt att specificera upprepning av en initialiserare - men GCC har en förlängning för att göra det.

C99

I C89 / C90 eller tidigare versioner av C fanns det inget sätt att initialisera ett element i mitten av en matris utan att tillhandahålla alla föregående värden också.

C99

Med C99 och högre tillåter designerade initialiserare dig att initiera godtyckliga element i en matris och lämna eventuella oinitialiserade värden som nollor.

Initiera karaktärsuppsättningar:

Teckenuppsättningar är ett speciellt fall av initialisering; en sträng kan användas istället för hängslen och kommateckningen:

char chr_array[] = "hello";

är en kortfattad längre men likvärdig:

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

I det här fallet är matrisstorleken sex (fem tecken plus avslutningen '\0' ).

1 Vad händer med en deklarerad, oinitialiserad variabel i C? Har det ett värde?

2 Observera att ett konstant uttryck definieras som något som kan utvärderas vid sammanställningstiden. Så int global_var = f(); är ogiltig. En annan vanlig missuppfattning är att tänka på en const kvalificerad variabel som ett konstant uttryck . I C betyder const "skrivskyddad", inte "kompilera tidskonstant". Så globala definitioner som const int SIZE = 10; int global_arr[SIZE]; och const int SIZE = 10; int global_var = SIZE; är inte lagliga i C.

Initiera strukturer och matriser av strukturer

Strukturer och matriser av strukturer kan initieras med en serie värden inneslutna i hängslen, ett värde per element i strukturen.

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
};

Observera att matrisinitialiseringen kunde skrivas utan de inre hängslen, och i tidigare tider (före 1990, säg) ofta skulle ha skrivits utan dem:

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

Även om detta fungerar är det inte bra modern stil - du bör inte försöka använda denna notation i ny kod och bör fixa kompilatorvarningarna som det vanligtvis ger.

Se även utsedda initialiserare .

Med hjälp av utsedda initialiserare

C99

C99 introducerade konceptet för utsedda initialiserare. Dessa låter dig specificera vilka element i en matris, struktur eller förening som ska initialiseras med följande värden.

Utformade initialiseringar för arrayelement

För en enkel typ som vanlig int :

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

Termen i fyrkantiga parenteser, som kan vara vilket som helst konstant heltaluttryck, anger vilket element i arrayen som ska initialiseras med värdet på termen efter = -tecknet. Ospecificerade element är standardinitialiserade, vilket innebär att nollor definieras. Exemplet visar de utsedda initialiserarna i ordning; de behöver inte vara i ordning. Exemplet visar luckor; de är legitima. Exemplet visar inte två olika initialiseringar för samma element; det är också tillåtet (ISO / IEC 9899: 2011, §6.7.9 Initiering, ¶19 Initieringen ska ske i ordningsföljd för initialiseringslistan, varje initierare tillhandahålls för ett visst underobjekt som åsidosätter alla tidigare listade initierare för samma underobjekt ).

I det här exemplet definieras inte storleken på matrisen uttryckligen, så det maximala indexet som anges i de angivna initialiserarna dikterar storleken på matrisen - vilket skulle vara 21 element i exemplet. Om storleken definierades skulle det som vanligt vara ett fel att initiera en post bortom slutet av matrisen.

Utformade initialisatorer för strukturer

Du kan ange vilka element i en struktur som ska initialiseras med . element notation:

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

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

Om element inte listas initieras de (nollställs).

Utformad initialisator för fackföreningar

Du kan ange vilket element i en union som ska initialiseras med en utsedd initialisator.

C89

Innan C-standarden fanns inget sätt att initiera en union . C89 / C90-standarden låter dig initiera den första medlemmen i en union - så valet av vilken medlem som listas är viktigast.

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

Observera att C11 låter dig använda anonyma fackmedlemmar i en struktur, så att du inte behöver du namnet i föregående exempel:

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 };

Utformade initialisatorer för matriser av strukturer osv

Dessa konstruktioner kan kombineras för matriser av strukturer som innehåller element som är matriser osv. Genom att använda hela uppsättningar av hängslen säkerställs att notationen är otvetydig.

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",
          }
 };

Ange intervall i arrayinitierare

GCC tillhandahåller ett tillägg som gör att du kan ange ett intervall av element i en matris som ska ges samma initialisator:

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

Trippelpunkterna måste vara separata från siffrorna så att en av punkterna inte kan tolkas som en del av ett flytande punktnummer ( maximal munchregel ).



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow