简体   繁体   中英

Why doesn't my C compiler warn when I assign a string literal to a non-const pointer?

The following code compiles fine with, for example, the default settings in Xcode 11.3.1:

#include <stdio.h>

int main(int argc, const char * argv[]) {
    char* thing = "123";
    thing[2] = '4';
    printf("%s\n", thing);
    return 0;
}

However, at runtime the code traps with EXC_BAD_ACCESS on thing[2] = '4' . I assume this is because the memory for the bytes representing "123" is compiled into my program's binary somewhere that on a modern processor/OS gets marked as for code rather than data . ( This answer confirms that — not to mention there's a leaq 0x4d(%rip), %rsi ; "123" line in the disassembly, passing the pointer to an address relative to the instruction pointer !)

Is it just a historical artifact that C allows this, from the era of self-modifying code? I notice that I can also assign void* x = main; without any complaint that I'm discarding modifiers.

This answer says:

According to the C99 rationale, there were people in the committee who wanted string literals to be modifiable, so the standard does not explicitly forbid it.

Is there any further discussion I could read on that? More practically, is there a way to tell clang and/or gcc to flag such assignments (even though they are not actually forbidden) with a warning , without compiling as C++?

The answer you have quoted is an opinion without citation, and frankly nonsense. It is about nothing more than not breaking the vast quantity of existing legacy C code that it is desirable to remain compilable in a modern compiler.

However many compilers will issue a warning if you set the necessary warning level or options. In GCC for example:

-Wwrite-strings

When compiling C, give string constants the type const char[length] so that copying the address of one into a non-const char* pointer produces a warning. These warnings help you find at compile time code that can try to write into a string constant, but only if you have been very careful about using const in declarations and prototypes. Otherwise, it is just a nuisance. This is why we did not make -Wall request these warnings.

When compiling C++, warn about the deprecated conversion from string literals to char *. This warning is enabled by default for C++ programs.

CLANG also has -Wwrite-strings , where is a synonym for -Wwriteable-strings

-Wwritable-strings

This diagnostic is enabled by default.

Also controls -Wdeprecated-writable-strings .

Diagnostic text:

 warning: ISO C++11 does not allow conversion from string literal to A

The diagnostic text is different for C compilation - I'm just quoting the manual.

In GCC with -Wwrite-strings :

int main()
{
    char* x = "hello" ;
    return 0;
}

produces:

main.c:3:15: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]    

CLANG produces:

source_file.c:3:15: warning: initializing 'char *' with an expression of type 'const char [6]' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]

Opposite to C++ In C string literals have types of non-constant character arrays.

However according to the C Standard any attempt to modify a string literal results in undefined behavior.

Historically the C language did not have the qualifier const. The qualifier const at first appeared in C++. So for the backward compatibility string literals in C have types of non-constant character arrays.

You have the -Wwrite-strings :

When compiling C, give string constants the type const char[length] so that copying the address of one into a non-const char * pointer produces a warning. These warnings help you find at compile time code that can try to write into a string constant, but only if you have been very careful about using const in declarations and prototypes. Otherwise, it is just a nuisance. This is why we did not make -Wall request these warnings.

https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Warning-Options.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM