Care este dimensiunea unei enumuri în C?


Cel mai bun răspuns

O enigmă foarte spinoasă, când trebuie să se potrivească compensările de structură peste limitele mașinii sau protocoalele de rețea . Specificația spune că dimensiunea trebuie să fie cea minimă necesară pentru a reprezenta cea mai mare valoare pe care o poate lua. Deci, o enumere tipică de stare a mașinii de stare, de exemplu, ar putea necesita doar un octet.

Există AFAIK doar trei moduri de a controla dimensiunea:

unele (dar nu toate) compilatoarele au un comutator de comutare pentru a forța dimensiunea fie la sizeof (int), fie la 32 de biți. Sintaxa comutatorului nu este aceeași între MSC și gccc / clang.

A doua modalitate, dacă trebuie să completați un câmp de 16 biți, este să definiți o valoare maximă falsă care necesită acea dimensiune.

Cealaltă modalitate este de a utiliza stiluri int obișnuite în definițiile structurilor, dar apoi se renunță la comoditatea depanatorului de a-i arăta valoarea după numele enum și se obțin doar numere întregi.

Apoi, probabil că va trebui să specificați structura care conține enum-ul este ambalat, nu căptușit.

Răspuns

Dacă nu există nicio parte a unei variabile x este const sau volatile și x nu este de tip tablou, apoi declarația …

x = x;

… aproape că nu face nimic. Este „bine format. Presupunând că x a fost inițializat în prealabil, ¹ este, de asemenea, bine definit. Schimbă într-adevăr starea programului, cu câteva potențiale excepții (vezi mai jos).

Acest lucru este adevărat chiar dacă x are un struct tip.

struct foo {

char buf[42];

int x;

};

struct foo x = { "Hello World", 18 };

x = x; // no big deal.

Deci, care este „greșeala”? Nu este util cod, dar există destul de multe coduri care se potrivesc acelei descrieri. Este doar o greșeală dacă intenționați să faceți altceva și ați ratat.

[Addendum: Având în vedere inutilitatea acestei misiuni, compilatoarele sunt înclinate să avertizeze în legătură cu aceasta, întrucât este foarte probabil id = „af7847d40e”>

înseamnă altceva.]

De ce un pic despre const și volatile? Restricția pentru const este simplă: înseamnă „numai citire” și astfel nu poți să-i scrii. Cel puțin, nu cu o simplă atribuire.

Cel referitor la volatile este mai complicat. Acest cuvânt cheie spune că valoarea calificată de acesta ar putea fi modificată în moduri care nu sunt vizibile pentru implementare și că scrisul pe acesta ar putea avea efecte secundare. Fără a săpăta într-o rathole aici, în practică, singurele operații rezonabile bine definite pe care le puteți efectua pe un obiect volatil arată astfel:

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.

Puteți face ceva mai mult decât atât cu bunătate cu volatile, dar doar puțin. Acesta este un subiect pentru o altă zi. Există un motiv pentru care C ++ 20 a renunțat la toate, cu excepția câtorva utilizări ale volatile. Schimbările lor par destul de sensibile.

Am menționat câteva excepții posibile mai sus. Jonas Oberhauser mi-a amintit că orice umplere într-un struct nu este neapărat păstrată de acea atribuire.

De asemenea, este teoretic posibil ca reprezentarea subiacentă pentru obiecte să se poată schimba datorită atribuirii, dacă aceeași valoare poate fi reprezentată în mai multe moduri.

Sperăm că programul dvs. nu este sensibil la ambele posibilități. Dacă vă uitați vreodată la reprezentarea subiacentă a obiectului, puteți vedea diferențe. Funcții precum memcmp ar putea observa, de exemplu. La fel, dacă utilizați tastați punning.

¹ Și dacă nu a fost, bine ați venit la comportament nedefinit, deoarece probabil că vă confruntați cu unul dintre acestea:

  • Valoarea unui obiect cu durata de stocare automată este utilizată în timp ce este nedeterminată ( 6.2 .4 , 6.7.9 , 6.8 ).
  • O valoare care desemnează un obiect cu durata de stocare automată care ar fi putut fi declarată cu clasa de stocare a registrului este utilizată într-un context care necesită valoarea obiectului desemnat, dar obiectul nu este inițializat. ( 6.3.2.1 ).

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *