Ответ 1
Строковые литералы С++ представляют собой массивы const char
, что означает, что вы не можете их законным образом модифицировать.
Если вы хотите безопасно назначить строковый литерал указателю (который подразумевает неявное преобразование между массивами и указателями), вам нужно объявить целевой указатель как const char*
, а не только как char*
.
Вот версия вашего кода, которая компилируется без предупреждений:
#include <iostream>
using namespace std;
struct WORDBLOCK
{
const char* string1;
const char* string2;
};
void f3()
{
WORDBLOCK word;
word.string1 = "Test1";
word.string2 = "Test2";
const char *test1 = word.string1;
const char *test2 = word.string2;
const char** teststrings;
teststrings = &test1;
*teststrings = test2;
cout << "The first string is: "
<< teststrings
<< " and your second string is: "
<< *teststrings
<< endl;
}
Подумайте, что может случиться, если язык не наложил это ограничение:
#include <iostream>
int main() {
char *ptr = "some literal"; // This is invalid
*ptr = 'S';
std::cout << ptr << "\n";
}
A (не const
) char*
позволяет вам изменять данные, на которые указывает указатель. Если вы можете назначить строковый литерал (неявно преобразованный в указатель на первый символ строки) в обычный char*
, вы сможете использовать этот указатель для изменения строкового литерала без предупреждения от компилятора. Недопустимый код выше, если он сработает, будет печатать
Some literal
- и это может на самом деле сделать это на некоторых системах. В моей системе, однако, он умирает с ошибкой сегментации, потому что он пытается записать в постоянную память (не физическое ПЗУ, а память, помеченную как операционная система только для чтения).
(В стороне: правила C для строковых литералов отличаются от правил С++. В C строковый литерал представляет собой массив char
, а не массив const char
- но попытка его изменения имеет undefined Это означает, что в C вы можете юридически написать char *s = "hello"; s[0] = 'H';
, и компилятор не обязательно будет жаловаться, но программа, скорее всего, умрет с ошибкой сегментации при ее запуске. Это было сделано для поддержания обратной совместимости с C код, написанный перед ключевым словом const
. С++ имел const
с самого начала, поэтому этот конкретный компромисс не был необходим.)