3
#include <stdio.h>

void print(char *strings[]) {
  while (*strings) printf("%s\n", *strings++);
}

int main(int argc, char *argv[]) {

  char *array[] = {"Hello", "World", NULL}; // No warning?
  const char *constArray[] = {"Hello", "World", NULL};

  print(constArray); // Warning!

  //constArray[0][0] = '!'; Compile time error
  array[0][0] = '!'; // Run time error

  return 0;
}

I was expecting to get a warning in char *array[] = {"Hello", "World", NULL}; because the characters of those strings are read only, but the compiler does not give me a warning about that. So basically the compiler is letting me "cast" a const char to a char a without warning.

When passing a const char to a function that receives a char in print(constArray);, in other words, "casting" a const char, to a char the compiler does give me a warning. I was expecting the compiler to give me a warning in both cases or in neither, but not in one case and not the other.

I think this warning is important to help prevent errors like in array[0][0] = '!';. So why I don't get a warning in the first initialization?

Rodrigo5244
  • 5,145
  • 2
  • 25
  • 36
  • Even if the strings are read only, the pointers are not. They can be changed without any warning, which is OK. – tofro Oct 09 '16 at 23:17
  • 1
    @tofro, yes, but that's beside the point. A value of type `const char *` cannot be assigned to an lvalue of type `char *` -- it violates paragraph 6.5.16/1 of the standard. The issue here is in part that "read only" is a poor description of string literals, and that it is anyway not equivalent to `const`. The standard does not say that string literals are read only; it says that attempting to modify their values produces undefined behavior. This is a fine but important distinction. – John Bollinger Oct 09 '16 at 23:28

2 Answers2

6

So why I don't get a warning in the first initialization?

Because the type of a string literal is array of char, not array of const char, notwithstanding the fact that modifying the elements of such an array produces undefined behavior. This comes down from the very first days of C, when there was no const. I'm sure its persistence into modern C revolves around the magnitude and scope of the incompatibility that would arise if the type were changed.

With respect to individual programs, however, GCC can help you out. If you turn on its -Wwrite-strings option then it will indeed give string literals type const char [length], with the result that a construct such as you presented will elicit a warning.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

The compiler doesn't warn you because the C standard doesn't require that string literals be const.

Why doesn't the compiler detect and produce errors when attempting to modify char * string literals?

Why do compilers allow string literals not to be const?

Community
  • 1
  • 1
David
  • 1,624
  • 11
  • 13
  • If the C standard did require the const qualifier, the compiler should give an error. It seems that this would be a useful case for a warning. – Theodore Norvell Jul 29 '23 at 03:19