У меня есть следующий пример, взятый отсюда:
// strings and c-strings
#include <iostream>
#include <cstring>
#include <string>
int main ()
{
std::string str ("Please split this sentence into tokens");
char * cstr = new char [str.length()+1];
std::strcpy (cstr, str.c_str());
// cstr now contains a c-string copy of str
char * p = std::strtok (cstr," ");
while (p!=0)
{
std::cout << p << '\n';
p = strtok(NULL," ");
}
delete[] cstr;
return 0;
}
Насколько я понимаю str
это строка, str.c_str()
указатель, указывающий на первый элемент массива, который содержит символы str
как его элементы. Затем с помощью std::strcpy
мы берем значение адреса, указанного в качестве второго аргумента, и присваиваем это значение указателю, указанному в качестве первого аргумента (cstr
).
Тем не менее, у меня есть следующий пример, взятый из Вот:
#include <iostream>
#include <cstring>
int main()
{
char *str = new char[100];
std::strcpy(str, "I am string!");
std::cout << str;
delete[] str;
}
И теперь в качестве второго аргумента у нас есть строка (а не указатель на массив, как это было в первом примере).
Кто-нибудь может, пожалуйста, прояснить это несоответствие?
При использовании std :: strcpy мы берем значение адреса, указанного в качестве его
второй аргумент и присвойте это значение указателю, который задан как
первый аргумент (cstr).
char * strcpy ( char * destination, const char * source );
Никакой strcpy фактически не читает каждый символ, указанный источником, и записывает их в месте назначения, он останавливается, когда он читает завершающий нулевой символ.
Во втором примере исходным аргументом является строковый литерал с типом const char []. Эта строка может быть преобразована в const char * для передачи в strcpy.
Строковый литерал не намного больше, чем указатель на местоположение только для чтения.
std::strcpy(str, "I am string!");
«Я строка!»
Строковый-буквальный. На самом деле это const char[13]
(это распадается на const char*
при переходе в функцию).
N3376 2.14.5 / 8
Обычные строковые литералы и строковые литералы UTF-8 также называются узкими строковыми литералами. Стрелка
строковый литерал имеет тип «массив из n const char», где n — это размер строки, как определено ниже, и имеет
статическая продолжительность хранения (3.7).
n3376 4.2 / 1 Неявное преобразование массива в указатель.
Lvalue или rvalue типа «массив N T» или «массив неизвестной границы T» может быть преобразован в значение
типа «указатель на T». Результатом является указатель на первый элемент массива.
И теперь в качестве второго аргумента у нас есть строка (а не указатель на массив, как это было в первом примере)
Во втором примере у вас есть строка C, которая является указателем на NUL-концевой массив символов. Здесь нет противоречий.
char *strcpy( char *dest, const char *src );
нужен указатель источника const char и он копирует память в указатель назначения, который имеет тип char. Функция копирует длину строки из источника, пока не найдет строку с нулем в конце источника. "I am string!"
является const char * const`, который является строковым литералом, который в основном хранится в памяти, помеченной только для чтения.