Beste svaret
Et veldig kjedelig råd, når man må matche strukturforskyvning på tvers av maskingrenser eller nettverksprotokoller. . Spesifikasjonen sier at størrelsen må være det minste som kreves for å representere den største verdien den kan ta. Så en typisk tilstandsstatus for enum kan for eksempel bare kreve en byte.
Det er bare tre måter å kontrollere størrelsen på AFAIK:
noen (men ikke alle) kompilatorer har en kompilatorbryter for å tvinge størrelsen til enten størrelse på (int) eller til 32 bits. Bryter-syntaksen er ikke den samme mellom si MSC og gccc / clang.
Den andre måten, hvis du trenger å fylle si et 16-biters felt, er å definere en dummy max-verdi som krever den størrelsen.
Den andre måten er å bruke vanlige int-stiler i strukturdefinisjonene, men da gir man avkall på feilsøkingsfunksjonen ved å få den til å vise verdien ved enumnavn, og bare få heltall i stedet.
Da vil en sannsynligvis trenge å spesifisere strukturen som inneholder enum er pakket, ikke polstret.
Svar
Hvis ingen del av noen variabel x
er const
eller volatile
, og x
er ikke av array-typen, så gjør utsagnet …
x = x;
… stort sett ingenting. Det er godt formet. Forutsatt at x
ble initialisert på forhånd, ¹ det er også veldefinert. Oppgaven ikke ikke virkelig endre tilstanden til programmet, med et par potensielle unntak (se nedenfor).
Dette gjelder selv om x
har en struct
type.
struct foo {
char buf[42];
int x;
};
struct foo x = { "Hello World", 18 };
x = x; // no big deal.
Så hva er «feilen»? Det er ikke nyttig kode, men det er ganske mye kode som passer til beskrivelsen. Det er bare en feil hvis du hadde som mål å gjøre noe annet og savnet.
[Tillegg: Gitt denne oppgaven «er nytteløshet, er samlere tilbøyelige til å advare om det, siden det er ganske sannsynlig at du gjorde betyr noe annet.]
Hvorfor litt om const
og iv id = «3bb41f7bd8» Begrensningen på const
er enkel: det betyr «skrivebeskyttet», så du kan ikke skrive til den. I det minste ikke med enkel oppgave.
Den angående volatile
er vanskeligere. Det nøkkelordet sier at verdien som kvalifiseres av det, kan endres på måter som ikke er synlige for implementeringen, og som skriver til det kan ha bivirkninger. Uten å grave i et rathole her, ser i praksis de eneste rimelig veldefinerte operasjonene du kan utføre på et flyktig objekt slik ut:
volatile int v;
int i;
i = v; // reads from v once, places into i.
v = i; // writes to v once with the contents of i.
Du kan gjøre litt mer enn det med sunnhet med volatile
, men bare litt. Det er et tema for en annen dag. Det er en grunn til at C ++ 20 avskaffet volatile
, bortsett fra noen få. Endringene deres ser ganske fornuftige ut.
Jeg nevnte et par mulige unntak ovenfor. Jonas Oberhauser minnet meg om at enhver polstring i en struct
er ikke nødvendigvis bevart av den oppgaven.
Det er også teoretisk mulig at underliggende representasjon for objekter kan endres på grunn av tildelingen, hvis den samme verdien kan vises på flere måter.
Forhåpentligvis er programmet ditt ufølsomt for begge mulighetene. Hvis du noen gang ser på den underliggende -representasjonen av objektet, kan du imidlertid se forskjeller. Funksjoner som memcmp
kan for eksempel legge merke til det. Likeledes hvis du bruker skriv punning.
¹ Og hvis det ikke var det, velkommen til udefinert oppførsel, som du sannsynligvis støter på en av disse:
- Verdien til et objekt med automatisk lagringsvarighet brukes mens det er ubestemt ( 6.2 .4 , 6.7.9 , 6.8 ).
- En verdi som angir et objekt med automatisk lagringsvarighet som kunne blitt deklarert med registerlagerklassen, brukes i en sammenheng som krever verdien av det angitte objektet, men objektet er ikke initialisert. ( 6.3.2.1 ).