C Language
initiering
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.
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å.
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 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.
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 } };
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 ).