4

What is a good way of creating a constant string in C? A string that cannot be mutated by doing character assignment to one of its indexed location. And a string that cannot be replaced by another string in later execution after initialization.

I tried both char* and char[] in the following code. I tried them with and without the "const" keywords. The outcome is very bizarre.

The following is my code:

#include <stdio.h>
main() {
    char a []= "abc" "def";
    char* b = "abcdef";
    const char c [] = "abcdef";
    const char* d = "abcdef";

    a[1] = 'y';
    b[1] = 'y';
    c[1] = 'y';
    d[1] = 'y';
    printf("%s %s %s %s \n", a, b, c, d);

    a = "overwrited";
    b = "overwrited";
    c = "overwrited";
    d = "overwrited";
    printf("%s %s %s %s \n", a, b, c, d);
}

The result is that In the first printf, all a, b, c, d can be mutated; but c and d appear warnings that "assignment of read-only location". In the second printf, both a and c return error. But b and d are smoothly replaced by another string and become "ovewrited".

I am very confused by this result that it seems like "const" keyword doesn't have the effect on doing string assignment; but it has effect on indexed character mutation. And char[] and char* show different behaviours as well. Could someone explain to me the mechanism behind this?

Erencie
  • 391
  • 2
  • 3
  • 12
  • 2
    @GregHewgill: I suggest you look again, this question isn't a duplicate of that one. – caf Aug 06 '13 at 06:08
  • 1
    [Difference between `char *str` and `char str[]` and how both stores in memory?](http://stackoverflow.com/questions/15177420/what-does-sizeofarr-return/15177499#15177499) – Grijesh Chauhan Aug 06 '13 at 06:46
  • @GrijeshChauhan Your link has enlightened me abt the differences btw char* and char[]. I add a little bit more code into my question so as to make it cover more abt the "constant" concept. – Erencie Aug 07 '13 at 16:28
  • @Erencie your question is asked many times in many ways so i elaborately answered there, if you need similar answer for 2D then go to my profile. Btw your question has been closed, and i flagged to reopen case you have any other doubt ask new one. – Grijesh Chauhan Aug 07 '13 at 16:38
  • 1
    @Erencie hope this answered your question http://coderek.github.io/blog/2013/08/08/c-string-notes/ – coderek Aug 09 '13 at 02:02

3 Answers3

3

If you wish to maximize the chances that your const arrays will be placed into actual read-only memory, you should make them static as well:

static const char c[] = "abcdef";

This is because all variables with automatic storage duration are normally created in the same area of memory, regardless of whether they are const-qualified or not. This area of memory therefore cannot be made read-only.

However, given that your implementation apparently doesn't place string literals into read-only memory either, it may not use read-only memory at all and the warning might be the best you can hope for. If you are using a gcc-based compiler, you could also try the -fno-writable-strings compiler option.


The reason that these two lines are errors:

a = "overwrited";
c = "overwrited";

is because a and c are arrays, and arrays cannot be directly assigned to with the = operator (regardless of whether they are const or not). The = in the variable declaration is not an = operator - it's just part of the initialisation syntax, and arrays can be initialised.

The reason that these lines are OK:

b = "overwrited";
d = "overwrited";

is because b and d are non-constant pointers to constant chars. These assignments don't mutate the original strings that b and d pointed to - they change b and d to point to different strings (possibly the same string, actually).

If you want b and d to be constant pointers (so that the pointer itself cannot be changed), you can change the declarations:

char * const b = "abcdef";
const char * const d = "abcdef";

..and the assignments to b and d should at least issue an error message from the compiler.

caf
  • 233,326
  • 40
  • 323
  • 462
  • What you mean is that, within a method, even if I add "const" keyword, it is still possible that the string is not a constant, because it would be created within an area of memory that's not read-only? That sounds quite string to me. In my experience with other languages, if I add a constant keyword, that string would be "fixed". – Erencie Aug 07 '13 at 16:35
  • The `char c[] = "abcdef";` is an initialization syntax, not assignment. And you can modify a `char c[]`, since after initialization `c` is not related to string literal at all. – NeoZoom.lua Apr 05 '21 at 18:00
  • As for `const char c[]`: it's just let the compiler do additional check that the __content__ of `c` is not modified through the name `c`. All the discussion here is not related to the string literal `"abcdef"` used in the initialization, and hence "why string literal can be modified" is not an issue here. – NeoZoom.lua Apr 05 '21 at 18:03
  • Both of you comment and answer are incorrect in my point of view. – NeoZoom.lua Apr 05 '21 at 18:10
  • @Rainning: The OP was not specifically asking about "string literals". The author was asking about creating a "constant string", which could be a string literal but could also be a named array. When an object is defined with the `const` type qualifier, it is undefined behaviour to modify that object (in the case of an array, this applies to the array elements), which in practice means that the implementation has latitude to store the object in read-only memory if it has such a thing. Using `static const char []` to store a string gives a good chance the string will be immutable. – caf Apr 07 '21 at 14:20
-1

const char c and const char* d both are constant and read only location on which you are trying to assign something new.Warnings with your compiler are actually error with mine(gcc 4.4.3).

1)Do not overlook warnings.

2)Modifying string literal is undefined behaviour.(fortunately you are getting expected output but it doesn't mean you are allowed.)

3)Increase strictness level of warnings and error in your compiler.

Dayal rai
  • 6,548
  • 22
  • 29
  • I am using a compiler called "tiny C Compiler" as I was looking for a lightweight C compiler so that I can play some C coding quickly. You're right. Warnings shouldn't be overlooked; it all depends on the strictness level in the settings of compiler. – Erencie Aug 07 '13 at 16:33
  • 2
    `d` itself is not a constant - it's a non-constant pointer to a constant. – caf Aug 07 '13 at 22:31
-2

1. constants

you could use the directive

\#define CONST_NAME  value

And then in your code file use the CONST_NAME. The preprocessor will replace the instances of CONST_NAME with value Also, what's the difference of and char[] in representing a character array, or a string in C?

2. char * and char[]

char* is a pointer to an object that is of type char. with no fixed size. the char* points to the fist char of your "string".

char[] is a array of char with a fixed size.

Usally it is easier to manage an char array than a pointer. But when u dont know the size of your "string" us a pointer.

I recommend reading about pointers. This is what C is about :)

lordkain
  • 3,061
  • 1
  • 13
  • 18