10

I can't figure out why I get this warning from clang by myself:

function_prototype_const_modifier.c:13:8: warning: initializing 'char *' with an
      expression of type 'const char *' discards qualifiers
      [-Wincompatible-pointer-types]
        char *ptr1 = source;
              ^      ~~~~~~
1 warning generated.

The code is very simple

#include<stdio.h>

char *my_strcpy(char *destination, const char *source);

int main(void) {
    char str1[] = "this is something";  
    char str2[] = "123456789123456789";
    my_strcpy(str2, str1);
    puts(str2);
    return 0;
}
char *my_strcpy(char *destination, const char *source) {
    char *ptr1 = source;
    char *ptr2 = destination;
    while(*ptr1 != '\0') {
        *ptr2++ = *ptr1++;
    }
    *ptr2 = '\0';
    return destination;
}

any idea?

mko
  • 21,334
  • 49
  • 130
  • 191

6 Answers6

18

source is a const char *, a pointer to const characters, so the characters cannot be changed by dereferencing the pointer (i. e. source[0] = 'A'; is a constraint violation).

However, assigning it to a char * discards this constraint; a simple char * suggests that the characters pointed to by the ptr1 pointer are not constant and you can now freely write ptr1[0] = 'A'; without getting compiler errors (a "diagnostic message").

Consider what this means when you pass in a string literal. Since a string literal is "readonly" (it's a const char []), trying to modify its contents is undefined behavior. So if you call

my_strcpy(destination, "Constant String");

but in the code for some reason you write

ptr1[0] = 'A';

you won't get a compiler diagnostic message because ptr1 is a pointer to non-const chars, but your program will still invoke undefined behavior (and in practice, most likely crash, since string literals are placed in readonly memory regions).

10

You just need to change:

char *ptr1 = source;

to:

const char *ptr1 = source;
Paul R
  • 208,748
  • 37
  • 389
  • 560
2

You are pointing to the same area in memory, but not qualifying it as const as well, which the argument is.

You then allow the function body to modify that part of memory which is labelled const.

alex
  • 479,566
  • 201
  • 878
  • 984
1

Because type of L.H.S is char * and type of R.H.S is const char *.

The reason is exactly as what error says:

function_prototype_const_modifier.c:13:8: warning: initializing 'char *' with an expression of type 'const char *' discards qualifiers

The statement allows you to discard the const qualifier and it allows to modify the pointed string through ptr1 and ptr2 and hence the compiler complains.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • I would think `const` meant the _pointer_ was constant and not the pointee. I would be mistaken. – John Dvorak Oct 22 '12 at 06:10
  • 1
    Jan read it right to left (helps me anyway). pointer to a character constant. char const * is a pointer constant to a character. – Lews Therin Oct 22 '12 at 06:11
  • @JanDvorak the `const` keyword applies to the term on its right, if there's no term on its right, only then applies the `const` keyword to the term on its left. –  Oct 22 '12 at 06:12
  • @H2CO3 agreed. And the term on its right is `char *`, a char pointer. – John Dvorak Oct 22 '12 at 06:13
1

You are assigning a pointer to a character constant to a pointer to a char. By doing that you risk modifying the character(s).

Lews Therin
  • 10,907
  • 4
  • 48
  • 72
0

In this case, just about what's we can do.

Thanks of clearness information for @user529758.

Just plus a answer.

Modified:

#include<stdio.h>

char *my_strcpy(char *destination, const char *source);

int main(void) {
    char str1[] = "this is something";  
    char str2[] = "123456789123456789";
    my_strcpy(str2, str1);
    puts(str2);
    return 0;
}
char *my_strcpy(char *destination, const char *source) {
    char *ptr1 = (char*)source;
    char *ptr2 = destination;
    while(*ptr1 != '\0') {
        *ptr2++ = *ptr1++;
    }
    *ptr2 = '\0';
    return destination;
}
rbbtsn0w
  • 75
  • 11