Aș dori să înțeleg modul în care C ++ procesează constantele tipurilor de bază.
Ce se va întâmpla dacă schimbați valoarea din celula de memorie folosind dansuri cu o tamburină și pointeri, unde teoretic ar trebui să fie conținută constant?
Există următorul cod:
Concluzia mea este următoarea:
Cum să explic acest comportament?
Nu voi folosi acest cod în practică, vreau doar să înțeleg unde sunt stocate constantele.
Pentru un început: conform standardului, o schimbare cu ajutorul cascadelor cu indicatori constanți este comportamentul nedefinit. Poate ceva se întâmplă oriunde în program.
Mai rău, dacă undeva compilatorul a dat seama pentru ei înșiși că constantă chiar și bitul cel mai puțin semnificativ este 0, iar pe baza acestor informații, ar putea elimina orice verificare a codului, acum verificați nu va trece, iar codul poate kreshnutsya în orice moment .
UB-urile au de obicei găuri de securitate în programe. De exemplu, în cazul în care compilatorul este în mod rezonabil crede că lungimea liniei 45, iar sub el este suficient să se aloce o lungime de tampon, în timp ce înșelându compilator arunca la el linia de lungime de 54, obținut printr-o defalcare stivă clasică.
Rezumat: Compilatorul nu are "obligații" sau "principii" pentru a lucra cu constante. El are dreptul să facă orice. Dimpotrivă, este un programator, dacă a promis că o anumită valoare este o constantă, nu are dreptul să o schimbe.
Conform standardului C ++ (7.1.6.1 CV-calificatorii)
4 Cu excepția faptului că orice membru al clasei este declarat mutabil (7.1.1) poate fi modificat, orice încercare de a modifica un obiect const pe durata sa de viață (3.8) duce la un comportament nedefinit
Există un anacronism în C, când chiar încercarea de a schimba un obiect neconstant conduce la un comportament nedefinit al programului. Este vorba despre literali de șir din C.
În C ++, literalul șirului are tipuri de matrice de caractere constante. De exemplu, șirul literal "Hello" este de tip const char [6]. Cu toate acestea, în C, literalurile de șir au tipuri de matrice non-constante de caractere. Prin urmare, același șir literal "Hello" în C are tipul char [6]. Cu toate acestea, nu puteți schimba literalul șir în C, la fel cum nu puteți schimba un literal șir în C ++.
De la standardul C (literalurile String 6.4.5)
7 Nu este specificat dacă aceste matrice sunt distincte, cu condiția ca elementele lor să aibă valorile corespunzătoare. Dacă programul încearcă să modifice o astfel de matrice, comportamentul este nedefinit.
Faptul că în literalurile de coarde C au tipuri de matrice non-constante de caractere este în mod evident asociat cu suportul unei baze de cod deja existente în momentul în care calificatorul const este introdus în standardul de limbă C.
Compilatorul este inteligent și știe că o constantă poate fi zainajnit. Dar există o ocazie să-l convingem că această constantă nu este prea constantă:
PS: În ceea ce îmi amintesc, volatile const este o situație valabilă, care nu trebuie să ducă la un comportament nedefinit.
el are tot dreptul să presupună că codul său nu schimbă exact obiectele const.
Pentru volatile nu contează. Imaginați-vă că există ceva extern care, "absolut accidental", schimbă aceeași constantă cu aceleași valori pe care le-am scris. Și în program, în loc de a schimba codul sunt nop'y. Această opțiune este absolut corectă și nu numește UB.