1

I am trying to implement an array of strings using pointer. Following is my code.

#include <stdio.h>
const int MAX = 4;
int main () {
char *names[] = {
  "abcd",
  "efgh",
  "ijkl",
  "mnop",
};
int i = 0;
for ( i = 0; i < MAX; i++) {
  printf("Value of names[%d] = %s\n", i, names[i] );
}
return 0;
}

I am having a warning at the time of running it. Following is the warning:

C:\workspace>g++ test_pointer_string_arr.c -o tpsa.exe
test_pointer_string_arr.c: In function 'int main()':
test_pointer_string_arr.c:12:4: warning: deprecated conversion from string       const
ant to 'char*' [-Wwrite-strings]
};
^
test_pointer_string_arr.c:12:4: warning: deprecated conversion from string const
ant to 'char*' [-Wwrite-strings]
test_pointer_string_arr.c:12:4: warning: deprecated conversion from string const
ant to 'char*' [-Wwrite-strings]
test_pointer_string_arr.c:12:4: warning: deprecated conversion from string const
ant to 'char*' [-Wwrite-strings]

what is the problem?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
LSG
  • 213
  • 3
  • 14
  • 5
    I'm getting these warnings only if I try to compile the code with a C++ compiler. With a C compiler, no warnings. – user3078414 May 10 '16 at 10:16
  • Possible duplicate of [this SO post](http://stackoverflow.com/questions/9650058/deprecated-conversion-from-string-literal-to-char). – user3078414 May 10 '16 at 10:18
  • 3
    You use extension `.c` for your code, but compile with `g++` which normally is used to call C++ code only. For C you should call `gcc`. C and C++ are **different** languages. – too honest for this site May 10 '16 at 10:23

2 Answers2

5

String literals, in C are non-mutable. Any attempt to change the content of a string literal invokes undefined behavior.

By definition, strings have the type char [], so, by assigning a string literal to a char * does not stop you from writing a code that silently invokes UB.

Regarding the gcc option, -Wwrite-strings

-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.

So, you need to write

 const char *names[] = {
  "abcd",
  "efgh",
  "ijkl",
  "mnop",
 };

and likewise.

As mentioned, most of the time, probably, it's not worthy.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 1
    "Strings" in C **never** have the type `char *`! And making string literals writeable is a bad idea and a violation of the standard. – too honest for this site May 10 '16 at 10:25
  • @Olaf Removed that part to avoid misunderstanding, the type is obviously not a pointer but array. Thanks for pointing the issue in writing. :) – Sourav Ghosh May 10 '16 at 10:31
  • @Olaf if you're talking about `-Wwrite-strings`, that does not "make string literals writeable" – M.M May 10 '16 at 11:53
  • @M.M I think Olaf was trying to mention that not using `const` qualifier is violation of standard, in the sense that string literals must not be allowed to mutate, not even _by chance_. – Sourav Ghosh May 10 '16 at 12:05
  • @M.M: You are right, it is just a warning. Still some compilers support them for compatibility with pre-ANSI C. – too honest for this site May 10 '16 at 12:06
  • @Olaf nobody suggested making string literals writable except you, and if a compiler does that then it is not a violation of the standard (because conforming code cannot make any such writes anyway) – M.M May 10 '16 at 12:14
2

The code is perfectly valid in C. However, you apparently compile for a different language: C++. g++ is the C++ frontend of the GNU Compiler Collection. While it might still use C mode due to the .c suffix, it enables other warnings.

As a general rule, you should use gcc to compile C code. In both languages writing to string literals is undefined behaviour (avoid under all circumstances). C is just less strict in enforcing const-correctness. That's why gcc has disabled this warning by default for C.

So, if you don't intend to change the strings in the array, you should always make the pointers to const char:

const char *names[] = ...

This helps the compiler detect illegal writes to the entries. You can also make the array itself const:

const char * const names[] = ...

That way you cannot change the entries. This is not only helpful for the compiler, but on some platforms (microcontroller) vital to store the data in non-modifyable memory.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52