Modifying a char *const string

主宰稳场 提交于 2019-11-26 23:09:19

t is pointing to a string literal it is undefined behavior to modify a string literal. The C++ draft standard section 2.14.5 String literals paragraph 12 says(emphasis mine):

Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation defined. The effect of attempting to modify a string literal is undefined.

The relevant section from the C99 draft standard is 6.4.5 String literals paragraph 6 which says(emphasis mine):

It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.

On a typical modern Unix platform you will find string literals in the read-only segment which would result in a access violation if we attempt to modify it. We can use objdump to inspect the read-only section as follows:

objdump -s -j .rodata

we can see in the following live example that the string literal will indeed be found in the read-only section. Note that I had to add a printf otherwise the compiler would optimize out the string literal. Sample `objdump output:

Contents of section .rodata:
 400668 01000200 776f726c 64002573 0a00      ....world.%s..

An alternative approach would be to have t point to an array with a copy of a string literal like so:

char r[] = "world";    
char *const t = r ;

Although string literals in C officially have a type of char[] (array of char, not const), the C standard specifically states that they must be treated as non-modifiable. Compilers tend to put string literals in a read-only segment, so attempting to modify them results in an access violation.

String literals are described in section 6.4.5 of the C11 standard (ISO/IEC 9899:2011).

You can bypass the compiler error by recast it as char*, as in *((char*)s + 1) = 'a'; but as it was already estated in other answers, this is undefined behaviour and will probably result in Segmentation Fault because you are editing a string literal.

If you want to test it properly, initialize the strings in a function so the initialization can be dynamic and use strdup() for that.

int
main(int argc, char **argv)
{
    char *d1 = strdup("hello");
    char *d2 = strdup("world");

    const char *s = d1;
    char *const t = d2;

    ...

    free(d1);
    free(d2);
}

The d1 and d2 variables are mainly used so that the dynamic allocations can be properly freed using free() at the end. Also, as other answers suggest, always treat string literals as const char *.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!