2013-07-11 2 views
5

Я проделал немного базового чтения и из того, что я собрал .c_str() всегда имеет нулевой терминатор.C++ memcpy для char * from c_str

У меня есть довольно простая программа на 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; 
} 

Будет ли тетсра обеспечить, чтобы скопировать над нулем строкой в ​​моем переменном (при условии, что моя строка из короче в длине)?

+1

Да, так как 'c_str()' всегда оканчивается нуль, но есть какая-либо конкретная причина для этого? – chris

+3

Зачем вы это делаете? Одной из основных сильных сторон std :: string является * not * использование необработанных массивов char, подобных этому. –

+3

Кстати, 'size()' или 'length()' даст вам постоянный размер времени, тогда как 'strlen()' является линейным. – chris

ответ

3

memcpy не знает, что такое строка. вы даете ему диапазон для копирования. это зависит от strlen здесь, чтобы обеспечить точку окончания диапазона

2

Да, это будет работать до тех пор, пока ваша строка в from короче 20. О, нет, подождите, мы также копируем терминатор NULL, поэтому он должен быть короче 19. Наверное, вы видите, как это может привести к некоторой путанице.

Это, кстати, именно причина, по которой этот код опасен: я предполагаю, что это демонстрационный код, и ваш фактический код получит эту строку из своего рода ввода. В этот момент вы не сможете контролировать, как долго это будет. Вы можете усечь его, но вы можете забыть сделать это, что означает, что ваша программа будет копировать содержимое в память, которая, возможно, не принадлежит ему. Это может привести к сбою, но, по крайней мере, к неопределенному поведению, поскольку вы переписываете память, которая может содержать другие важные данные.

Использование класса string действительно помогает избежать таких проблем, не указывая длину строки. Я бы предложил использовать этот класс и выполнять операции только с c_str(), когда это абсолютно необходимо.

0

Ответ на ваш вопрос: «Да» (если вы достаточно массив символов, вы должны поставить шаг проверки).

Если вы действительно хотите сделать это, вы можете сделать:

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; 
} 

Что безопаснее до тех пор, пока вы не пишете другой, более длинная строка в «до»

3

Вы должны использовать std::string для копировать строки. Тем не менее, если вы хотите сделать это так, что вы должны использовать strcpy вместо 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; 
} 
Смежные вопросы