I decided to go back to the SI and read the K & R book, and here I stumbled again on the topic of pointers, logically everything seems to be clear, but there are some problems with char * and const char * .

Let me give the code and show that all of these are 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 us draw a line over all these examples: Why in the first example can I not change each literal separately? (I did not declare an object as constant as in the second example)

PS The third example cited for the overall picture to show that everything works if you enter an additional parameter

    4 answers 4

    In the first and second case, you work directly with a string literal .

    In C, you have no control over const qualification such as a string literal. This const qualification is uniquely defined by language. The type of string literal in C is char [N] . And despite the fact that the type of a string literal does not formally contain a const qualifier, the string literal is nonetheless an immutable (non-modifiable) object. Attempts to change a string literal, like any other unmodifiable object, lead to undefined behavior.

    As you declared your pstr pointer — with or without const — the type and properties of the string literal have no effect. Your pointer has nothing to do with the string literal itself. Your pointer is nothing more than an access path to the real object. The constancy of the 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 modified objects and non-constant access paths to non-modifiable 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 is in no way dependent on the constancy of the access path to it (for the latter is easily removable).

    Given that the literal is an immutable object, pointing to string literals with a non-constant pointer (as in your first example) makes no sense, even if the language allows you to do it formally.

    In the third variant, you do not work directly with the string literal, but create your own modifiable array, which is only initialized by 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 as you like.

    • Comments are not intended for extended discussion; conversation moved to chat . - PashaPash

    According to the C language standard (6.4.5 String literals)

    7 It is unspecified. The behavior is undefined.

    That is, you cannot change string literals, despite the fact that they have types of non-constant character arrays. The fact that in C string literals are of the type of non-constant arrays, this is done for backward compatibility of C programs.

    Therefore, in this sentence

     char *pstr = "Hello, world"; 

    The string literal used as the initializer of the pstr pointer is implicitly converted to a pointer of type char * , rather than a pointer of type const char * that points to the first character of the literal.

    In C ++, string literals have the type of constant character arrays, thus avoiding misunderstanding.

    In the third example

     char str[] = "Hello, world"; char *pstr = str; *pstr = 'D'; 

    the pstr pointer pstr no longer dealing with a string literal, but with a user-defined character array. A string literal is only used to initialize the elements of a character array with its own characters. Since the array is declared as not constant, its elements can be changed.

    • Is it possible to somehow initialize a pointer of type int only? - MaximPro

    not sufficiently type safe and allows assignment of non-constant pointers to the address of a string literal. The fact that the pointer on the left side is not constant does not mean that you can change what it points to. Assigning a pointer does not create an additional object under the string and does not copy the right-hand side into it.

    So Your view code:

     char *pstr = "Hello, world"; *pstr = 'D'; 

    essentially equivalent to this (more obvious to demonstrate the option):

     "Hello, world"[0] = 'D'; 

    In this form, even gcc reports the corresponding warning:

    warning: assignment of read-only location '"Hello, world" [0]'

    The standard states unequivocally that an attempt to modify a string literal leads to undefined behavior (6.4.5 / 7):

    The behavior is undefined.

      A string literal is constant by definition. It can generally be placed in read-only memory. For example, VC ++ in the first example will skip code, there will be no failures - but the string will not change when it is executed.

      • hmm i heard about this that is, even though we have not specified the const specifier, the compiler will still think that we have it specified? but why in this case does not it give an error? - MaximPro
      • Let the standards specialists explain it. I have a suspicion that the reasons are purely historical, but this is nothing more than mine imho :) - Harry
      • there will be failures in general - the modification of a string literal is an undefined behavior, and the program should crash when launched. - ampawd
      • @ampawd Indefinite behavior and crashing are all different things. And with VC ++ - checked many times ... - Harry
      • @Harry are related things, if an undefined behavior occurs (for example, in this case), the OS usually catches and terminates the program as an emergency. I don’t know what you’ve checked out, but my visual studio 2015 crashes (or run time error, crashing, etc) - ampawd