2013-07-11 19 views
5

Zrobiłem trochę podstawowego czytania i z tego, co zebrałem. C_str() zawsze ma terminator o wartości NULL.C++ memcpy to char * from c_str

Mam dość prosty program w C++

int main(int argc, char** argv) 
{ 
    std::string from = "hello"; 
    char to[20]; 
    memcpy(to, from.c_str(), strlen(from.c_str())+1); 
    std::cout<< to << std::endl; 
    return 0; 
} 

Will że memcpy upewnić się, że mogę skopiować na sznurku nul do mojego zmiennej (pod warunkiem, że mój ciąg jest krótszy od długości)?

+1

Tak, ponieważ 'c_str()' jest zawsze zakończony zerem, ale czy jest jakiś szczególny powód, dla tej operacji? – chris

+3

Dlaczego robisz to w ogóle? Jedną z głównych zalet std :: string jest * nie * używanie surowych tablic o char w ten sposób. –

+3

Nawiasem mówiąc, 'size()' lub 'length()' przyniosą ci stałą wielkość czasu, podczas gdy 'strlen()' jest liniowa. – chris

Odpowiedz

3

memcpy nie wie, co to jest ciąg znaków. dajesz zakres do skopiowania. to zależy od strlen tutaj, aby podać punkt końcowy zakresu od

2

Tak, to będzie działało tak długo, jak długo ciąg znaków w from jest krótszy niż 20. O nie, czekaj, kopiujemy również terminator NULL, więc musi być krótszy niż 19. Zgaduję, jak to może prowadzić do pewnego zamieszania.

Co jest przy okazji dokładnie powodem, dla którego ten kod jest niebezpieczny: Zakładam, że jest to kod demo i twój rzeczywisty kod dostanie ten ciąg z jakiegoś wejścia. W tym momencie nie będziesz w stanie kontrolować, jak długo to trwa. Możesz go skrócić, ale możesz zapomnieć o tym, co oznacza, że ​​twój program będzie kopiował zawartość do pamięci, która prawdopodobnie do niego nie należy. Może to spowodować awarię, ale przynajmniej niezdefiniowane zachowanie podczas nadpisywania pamięci, która może zawierać inne ważne dane.

Korzystanie z klasy pomaga uniknąć takich problemów, nie określając długości ciągu znaków. Proponuję używać tej klasy i wykonywać tylko operacje obejmujące c_str(), gdy jest to absolutnie konieczne.

0

Odpowiedź na twoje pytanie brzmi "tak" (o ile tablica znaków jest wystarczająco duża, powinieneś wprowadzić krok weryfikacyjny).

Jeśli naprawdę chcesz to zrobić, można zrobić:

int main(int argc, char** argv) 
{ 
    std::string from = "hello"; 
    char* to = new char[from.length() + 1]; 
    memcpy(to, from.c_str(), from.length() + 1); 
    std::cout<< to << std::endl; 
    delete[] to; 
    return 0; 
} 

który jest bezpieczniejszy, o ile nie piszesz kolejny, dłuższy łańcuch na „do”

3

Należy użyć std::string do skopiuj ciągi. Jednakże, jeśli chcesz zrobić to tak, że należy użyć strcpy zamiast memcpy

int main(int argc, char** argv) 
{ 
    std::string from = "hello"; 
    char to[20]; 
    strcpy(to, from.c_str()); 
    std::cout<< to << std::endl; 
    return 0; 
}