Search code examples
cstring-literalsunsigned-char

In C11, string literals as char[], unsigned char[], char* and unsigned char*


Usually string literals is type of const char[]. But when I treat it as other type I got strange result.

unsigned char *a = "\355\1\23";

With this compiler throw warning saying "pointer targets in initialization differ in signedness", which is quite reasonable since sign information can be discarded.

But with following

unsigned char b[] = "\355\1\23";

There's no warning at all. I think there should be a warning for the same reason above. How can this be possible?

FYI, I use GCC version 4.8.4.


Solution

  • The type of string literals in C is char[], which decays to char*. Note that C is different from C++, where they are of type const char[].

    In the first example, you try to assign a char* to an unsigned char*. These are not compatible types, so you get a compiler diagnostic message.

    In the second example, the following applies, C11 6.7.9/14:

    An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

    Meaning that the code is identical to this:

    unsigned char b[] = 
    { 
      '\355',
      '\1',
      '\23',
      '\0'
    };
    

    This may yield warnings too, but is valid code. C has lax type safety when it comes to assignment1 between different integer types, but much stricter when it comes to assignment between pointer types.

    For the same reason as we can write unsigned int x=1; instead of unsigned int x=1u;.

    As a side note, I have no idea what you wish to achieve with an octal escape sequence of value 355. Perhaps you meant to write "\35" "5\1\23"?


    1 The type rules of initialization are the same as for assignment. 6.5.16.1 "Simple assignment" applies.