为什么我能够更改const char*ptr的内容?

And*_*sne 9 c pointers

我传递了一个指向ptr函数的指针,该函数的原型将其作为const.

foo( const char  *str );
Run Code Online (Sandbox Code Playgroud)

根据我的理解,这意味着它将无法改变ptr传递的内容.就像在的情况一样foo( const int i ).如果foo()尝试更新值i,编译器会给出错误.
但在这里我看到它可以ptr轻松改变内容.
请查看以下代码

foo( const char  *str )
{
        strcpy( str, "ABC" ) ;
        printf( "%s(): %s\n" , __func__ , str ) ;
}

main()
{
        char ptr[  ] = "Its just to fill the space" ;
        printf( "%s(): %s\n" , __func__ , ptr ) ;
        foo( const ptr ) ;
        printf( "%s(): %s\n" , __func__ , ptr ) ;
        return;
}
Run Code Online (Sandbox Code Playgroud)

在编译时,我只收到警告,没有错误:

warning: passing argument 1 of ‘strcpy’ discards qualifiers from pointer target type

当我运行它时,我得到一个输出而不是 Segmentation Fault

main():它只是填充空间
foo():ABC
main():ABC

现在,我的问题是
1什么const char *str的原型实际上是指?
这是否意味着功能无法改变内容str?如果是这样,那么上面的程序如何改变价值呢?
2-如何确保我传递的指针内容不会被更改?

从上述问题中的"指针的内容",我的意思是"由指针指向的存储器的内容",而不是"指针中包含的地址".

编辑

大多数回复说这是因为strcpy和C隐式类型转换.但是现在我尝试了这个

foo( const char  *str )
{
        str = "Tim" ;
//      strcpy( str, "ABC" ) ;
        printf( "%s(): %s\n" , __func__ , str ) ;
}
Run Code Online (Sandbox Code Playgroud)

这次是输出,没有编译器的警告

main():它只是为了填充空间
foo():Tim
main():它只是为了填补空间

因此很明显,内存指向str改为包含内存位置"Tim",而它的foo().虽然我没有用strcpy()这个时间.
const应该阻止这个吗?或者我的理解是错的?

对我而言,即使使用const,我也可以更改内存引用和内存引用的内容.那有什么用呢?

你能给我一个例子,编译器会给我错误,我试图改变一个const指针吗?

感谢大家的时间和精力.

Ale*_*x B 17

你的理解是正确的,const char*是一个契约意味着你无法通过这个特定的指针改变记忆.

问题是C 类型转换非常宽松.strcpy获取一个指向非const char 的指针,它被隐式转换const char*char*(正如编译器有用地告诉你).您可以轻松传递整数而不是指针.因此,您的函数不能更改指向的内容ptr,但strcpy可以,因为它看到非const指针.你没有崩溃,因为在你的情况下,指针指向一个足够大小的实际缓冲区,而不是一个只读字符串文字.

要避免这种情况,请查找编译器警告,或编译,例如,使用-Wall -Werror(如果您使用的是gcc).

此行为特定于C. C++,例如,不允许这样做,并且需要显式强制转换(C样式转换或a const_cast)来剥离const限定符,正如您合理预期的那样.

回答扩展问题

您正在将字符串文字分配给非const char,遗憾的是,它在C语言甚至是C++中都是合法的!它被隐式转换为char*,即使通过此指针写入现在将导致未定义的行为.这是一个不推荐使用的功能,到目前为止只有C++ 0x不允许这种情况发生.

话虽如此,为了停止更改指针本身,你必须将它声明为char(char *const)的const指针.或者,如果要使其指向的内容和指针本身都不会更改,请使用const指针指向const char(const char * const).

例子:

void foo (
        char *a,
        const char *b,
        char *const c,
        const char *const d)
    {
    char buf[10];
    a = buf; /* OK, changing the pointer */
    *a = 'a'; /* OK, changing contents pointed by pointer */

    b = buf; /* OK, changing the pointer */
    *b = 'b'; /* error, changing contents pointed by pointer */

    c = buf; /* error, changing pointer */
    *c = 'c'; /* OK, changing contents pointed by pointer */

    d = buf; /* error, changing pointer */
    *d = 'd'; /* error, changing contents pointed by pointer */
}
Run Code Online (Sandbox Code Playgroud)

对于所有错误行,GCC给出了"错误:分配只读位置".