为什么我得到;使用'const char *'类型的表达式初始化'char *'会丢弃限定符?

时间:2012-10-22 06:06:03

标签: c

我无法弄清楚为什么我自己从clang收到此警告:

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.

代码很简单

#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;
}

任何想法?

6 个答案:

答案 0 :(得分:13)

sourceconst char *,指向const字符的指针,因此无法通过解除引用指针来更改字符(即source[0] = 'A';是违反约束的行为)。

但是,将其分配给char * 会丢弃此约束;一个简单的char *表明ptr1指针指向的字符不是常量,您现在可以自由地编写ptr1[0] = 'A';而不会出现编译器错误(“诊断消息”)。

考虑传递字符串文字时这意味着什么。由于字符串文字是“只读”(它是const char []),因此尝试修改其内容是未定义的行为。所以,如果你打电话

my_strcpy(destination, "Constant String");

但是在代码中由于某种原因你写了

ptr1[0] = 'A';

您将不会收到编译器诊断消息,因为ptr1是指向非常量字符的指针,但您的程序仍将调用未定义的行为(实际上,很可能崩溃,因为字符串文字放在只读内存区域。)

答案 1 :(得分:5)

你只需要改变:

char *ptr1 = source;

为:

const char *ptr1 = source;

答案 2 :(得分:1)

因为L.H.S的类型是char *,而R.H.S的类型是const char *

原因正如错误所说:

  

function_prototype_const_modifier.c:13:8:警告:使用'const char *'类型的表达式初始化'char *'会丢弃限定符

该语句允许您放弃const限定符,并允许通过ptr1ptr2修改指向的字符串,因此编译器会抱怨。

答案 3 :(得分:1)

您正在将指向字符常量的指针指定给指向char的指针。 通过这样做,你冒着修改角色的风险。

答案 4 :(得分:1)

你指向内存中的同一区域,但也没有将其限定为const,参数是。

然后允许函数体修改标记为const的那部分内存。

答案 5 :(得分:0)

在这种情况下,我们可以做些什么。

感谢@ user529758的清晰信息。

加上答案。

修改:

#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;
}