ALGO25 / BLOG

memset sau fill: octeți și valori în C++

Înțelege de ce umplerea octeților cu 1 nu înseamnă atribuirea valorii întregi 1. Alege operația potrivită pentru inițializarea elementelor unui tablou.

std::fill atribuie o valoare fiecărui element dintr-un interval. std::memset umple o zonă de memorie cu un octet repetat. Diferența este esențială când un element, precum int, ocupă mai mulți octeți.

Valoarea unu nu este un octet repetat

Dacă un int are patru octeți în mediul folosit, umplerea celor patru octeți cu valoarea 1 produce modelul 01 01 01 01. Acesta nu reprezintă valoarea întreagă 1 în reprezentările obișnuite ale unui int de 32 de biți.

Prin urmare, o operație memset cu al doilea argument 1 nu este echivalentă cu atribuirea lui 1 fiecărui element. Programul poate compila și totuși să pornească de la valori complet diferite de cele intenționate.

Atribuie elementelor când gândești în valori

Pentru un tablou clasic, fill pe intervalul [a,a+n) atribuie valoarea cerută celor n elemente utile. Pentru un vector, intervalul begin..end acoperă elementele construite. O buclă simplă de atribuire exprimă aceeași intenție.

Această abordare este clară pentru zero, unu, o santinelă sau orice altă valoare compatibilă cu tipul elementelor. Nu cere să deduci reprezentarea internă în octeți a fiecărei valori.

Într-un int obișnuit de 32 de biți, repetarea octetului 01 în toate cele patru poziții produce modelul 01 01 01 01, nu valoarea întreagă 1.Într-un int obișnuit de 32 de biți, repetarea octetului 01 în toate cele patru poziții produce modelul 01 01 01 01, nu valoarea întreagă 1.Mărește schema ↗

Numărul de octeți este altă unitate

Al treilea argument al lui memset este un număr de octeți, nu un număr de elemente. Confundarea unităților poate inițializa doar o parte din tablou. Într-o funcție care primește un pointer, sizeof pe acel pointer nu dă dimensiunea tabloului original.

În plus, umplerea brută a memoriei nu este o operație generală de inițializare pentru obiecte precum string sau vector. Acestea au reguli de construcție și stare internă care nu trebuie înlocuite prin rescriere arbitrară de octeți.

Nu generaliza trucurile de reprezentare

Unele modele de octeți sunt folosite frecvent în cod de concurs pentru anumite tipuri și platforme. Popularitatea unui truc nu îl face portabil pentru orice tip, valoare și versiune de limbaj. Pentru o lecție și o soluție ușor de verificat, atribuirea valorii este de obicei mai explicită.

Testează câteva elemente după inițializare și verifică dacă intervalul acoperit este exact cel dorit. Nu confunda un rezultat observat pe o platformă cu o justificare independentă de reprezentarea datelor.

Continuă cu tablourile, tipurile de date și parametrii tablou.

Întrebări frecvente

Care este diferența dintre memset și fill?

memset repetă un octet într-o zonă de memorie. fill atribuie o valoare fiecărui element al unui interval. Diferența contează pentru tipuri cu mai mulți octeți, precum int.

De ce memset cu valoarea 1 nu pune fiecare int la 1?

El pune octetul 1 în fiecare poziție de memorie. Într-un int obișnuit de patru octeți apare modelul 01 01 01 01, nu reprezentarea numerică a întregului 1.

Ce folosesc pentru a umple un tablou cu o valoare numerică?

Preferă atribuirea pe elemente, de exemplu std::fill, pe intervalul valid. Astfel exprimi valoarea dorită direct, fără să presupui cum este reprezentată în octeți.