2012-11-10 18 views
33

Rozumiem, czym jest definicja memset(). Jednak nie rozumiem, o co w tym chodzi.Definicja pamięci i użycie

Definicja: Ustawia pierwszą liczbę bajtów bloku pamięci wskazywaną przez ptr na określoną wartość (interpretowaną jako unsigned char).

Czy ten kod jest wartością w adresie pamięci?

memset(&serv_addr,0,sizeof(serv_addr) jest przykładem, który próbuję zrozumieć.

Czy ktoś może wyjaśnić w bardzo uproszczony sposób?

+2

Jest używany głównie do inicjowania struktur i tablic. – imreal

+0

, więc to tak, jakby powiedzieć tablica [wartość]? dlaczego po prostu nie robić tego w ten sposób, jaki jest sens używania memset? –

+0

Możesz zrobić to jak 'array [wartość]' tylko jeśli znasz wartość 'value' podczas kompilacji (to jest C/C++). – irrelephant

Odpowiedz

38

memset() jest bardzo szybka wersja stosunkowo prostej operacji:

void* memset(void* b, int c, size_t len) { 
    char* p = (char*)b; 
    for (size_t i = 0; i != len; ++i) { 
     p[i] = c; 
    } 
    return b; 
} 

Oznacza to, memset(b, c, l) ustawić l bajtów zaczynając od adresu b wartości c. Robi to znacznie szybciej niż w powyższej implementacji.

+1

Dziwne, masz inicjalizator C++, ale odlewany C ... – Neil

+0

@Neil: dobry punkt - jestem osobą C++ i zdałem sobie sprawę, że polegam na konwersji. Zmienię kod na C i C++. –

+0

Jako kod, twoja funkcja ma zdefiniowane zachowanie implementacji, ponieważ 'c' może być poza zakresem dla typu' char'. Powinieneś zamiast tego zdefiniować 'p' jako' unsigned char * p = (unsigned char *) b; '(rzutowanie jest wymagane tylko w C++). – chqrlie

26

jest zwykle używany do inicjowania wartości. Na przykład rozważmy następujący struct:

struct Size { 
    int width; 
    int height; 
} 

przypadku utworzenia jednego z nich na stosie tak:

struct Size someSize; 

Następnie wartości w tej struktury będą niezdefiniowane. Mogą być zerowe, mogą być dowolnymi wartościami, które pojawiły się tam, kiedy ta część stosu była ostatnio używana. Więc zwykle byś podążać tą linię:

memset(&someSize, 0, sizeof(someSize)); 

Oczywiście może to być wykorzystywane do innych scenariuszy, to tylko jeden z nich. Wystarczy pomyśleć o tym, aby po prostu ustawić część pamięci na określoną wartość.

+2

Biorąc pod uwagę pytanie o to, co jest punktem memset, ta odpowiedź jest lepsza niż zaakceptowana imho. –

3

Chyba że serv_addr jakiś lokalny lub zmienna globalna jakiegoś struct typu -perhaps struct sockaddr - (a może class).

&serv_addr przyjmuje adres tej zmiennej. Jest to poprawny adres, podany jako pierwszy argument do memset. Drugi argument do memset to bajt do wypełnienia (zero bajtów). Ostatnim argumentem dla memset jest rozmiar, w bajtach, tej strefy pamięci do wypełnienia, która jest wielkością tej zmiennej serv_addr w twoim przykładzie.

To połączenie z memset usuwa globalną lub lokalną zmienną serv_addr zawierającą około struct.

W praktyce GCC kompilator, gdy jest optymalizacja, wygeneruje sprytny kod, który zwykle rozwinięciem i inline go (właściwie, to jest często wbudowane, więc GCC może wygenerować kod bardzo sprytnego dla niego).

5

memset to popularny sposób ustawienia regionu pamięci na 0 niezależnie od typu danych. Można powiedzieć, że memset nie dba o typ danych i po prostu ustawia wszystkie bajty na zero.

IMHO w C++ należy unikać robienia memset, gdy tylko jest to możliwe, ponieważ omija bezpieczeństwo typu, które zapewnia C++, zamiast tego należy użyć konstruktora lub inicjalizacji jako sposobu inicjowania. memset wykonany na instancji klasy może także zniszczyć coś nieumyślnie:

np.

class A 
{ 
public: 
    shared_ptr<char*> _p; 
}; 

memset na wystąpienie z powyższym nie zrobić odniesienia licznik ubytek prawidłowo.

+1

Ta odpowiedź powinna znajdować się wyżej na liście. Nie jest bezpiecznie używać memsetu w C++. – mwm314

1

To nic innego jak ustawienie pamięci na określoną wartość.

Oto przykład kodu.

Zasób (const * p, unit8_t V, unit8_t L), Tutaj P jest wskaźnikiem do pamięci docelowej, V jest wartością bufora docelowego, która będzie ustawiona na wartość V, a l jest długością dane.

while(L --> 0) 
{ 
    *p++ = V; 
} 
+0

Dobry przykład downto do operatora '->', ale jestem bardzo sceptyczny co do rodzaju argumentu 'L':' unit8_t' powinno być 'size_t'. – chqrlie

0

memset- zestaw bajtów pamięci

Synopsis-

#include<string.h> 

nieważne * memset (void * s, Int C size_t n)

Description memset () funkcja kopiuje c (konwertowane na unsigned char) do każdego z pierwszych n bajtów obiektu wskazanego przez s. Tutaj dla powyższej funkcji, memset() powinien zwrócić wartość s.

+1

W jaki sposób ta odpowiedź dodaje wartość do 4-letniego postu z 5 innymi odpowiedziami? –

+0

Szukałem odpowiedzi i poznałem tę definicję z innego źródła. Pomyślałem, że byłoby to pomocne dla innych osób, które szukają tego. – Ashit

0

Ja również poszukuje - dlaczego używać memset

chociaż tutaj jest coś, co stało się ze mną.

Użyłem strncpy (dest, source, number of chars) i otrzymałem niepoprawne wyniki. chociaż byłem pewien rozmiaru komórki docelowej.

, więc kiedy użyłem memset przed strncpy - mam świetne poprawne wyniki dla wyjścia strncpy. Zbadam dalej i zgłoś.

+0

Obawiam się, że ta odpowiedź jest kompletna bez sensu: 'strncpy', której powinieneś używać, ponieważ nie robi to, co myślisz, ** powoduje umieszczenie tablicy docelowej na' '\ 0'' po końcu ciąg źródłowy, jeśli wspomniany łańcuch źródłowy jest krótszy niż miejsce docelowe. Jednak ** nie ** null kończy miejsce docelowe, jeśli łańcuch źródłowy jest zbyt długi. Użycie 'memset' przed wywołaniem' strncpy' niczego nie zmienia. Musiałeś przekazać niepoprawną wartość dla argumentu size, na przykład długość łańcucha źródłowego, co jest częstym błędem. – chqrlie

+0

dziękuję za komentowanie. czy możemy użyć strncpy do wykonania procedury podłańcuchowej jak poniżej: strncpy (one_char_prod_arr [pcount], token.data.scalar.value, 1); jeden_char_prod_arr otrzymuje pierwszy znak wartości token.data.scalar.value –

+0

Nie zaleca się używania 'strncpy' do tego ani w żadnym celu. Możesz użyć 'memcpy()', aby wyodrębnić część ciągu, ale upewnij się, że ręcznie dodajesz terminator o wartości null. – chqrlie

Powiązane problemy