Question:
I decided to return to SI and read the K&R book, and then again I stumbled on the topic of pointers, by logic everything seems to be clear, but there are some problems with char *
and const char *
.
Let me give you the code and show that everything is not clear to me!
Example 1:
char *pstr = "Hello, world";
*pstr = 'D'; /// При запуске приложения на этом месте вылетит сбой не понятно!
printf(pstr); /// Ну и конечно ничего не выведет, измененную строку я не получу, ой точнее массив из символов
Example 2:
const char *pstr = "Hello, world";
*pstr = 'D'; /// Сбоя не будет и программа вообще не скомпилируется т.к компилятор сообщит что мы не можем изменять наш константный объект
printf(pstr); /// До сюда дело не дойдет
Example 3:
char str[] = "Hello, world";
char *pstr = str;
*pstr = 'D'; /// Все ок мы успешно поменяем наш первый элемент массива
printf(pstr); /// Мы получим это: "Dello, world"
Let's draw a line over all these examples: Why can't I change each literal separately in the first example? (I didn't declare the object constant as in the second example)
PS The third example is given for the general picture to show that everything works if you enter an additional parameter
Answer:
In the first and second case, you work directly with a string literal .
In C, you have no control over the const type qualification of a string literal. This const qualification is uniquely defined by the language. The type of a string literal in C is char [N]
. And despite the fact that the type of a string literal does not formally contain the const
qualifier, a string literal is nonetheless an immutable (unmodifiable) object. Attempts to modify a string literal, like any other unmodifiable object, lead to undefined behavior.
How you declared your pstr
pointer – with or without const
– has no effect on the type and properties of the string literal. Your pointer has nothing to do with the string literal as such. Your pointer – it is nothing more than an access path (access path) to the real object. The constancy of an access path is nothing more than an element of self-discipline, which in general is not related to the constancy of the object to which this path leads. The C language provides you with the means to legally create both constant access paths to modifiable objects and non-constant access paths to unmodifiable objects.
int a = 42;
const int *pa = &a; // константный путь доступа к модифицируемому объекту
const int b = 5;
int *pb = (int *) &b; // неконстантный путь доступа к немодифицируемому объекту
Ultimately, the possibility of legal modification of an object is determined precisely and only by the modifiability of the object itself and does not in any way depend on the constancy of the access path to it (for the latter is easily removable).
Considering that a literal is an immutable object, there is no point in pointing to string literals with a non-const pointer (as in your first example), even if the language formally allows you to do so.
In the third option, you do not work with the string literal directly, but create your own modifiable array, which is only initialized with the value of the string literal. Those. your array contains a self-contained copy of the string literal value. This is your own array and you can modify it however you like.