gpt4 book ai didi

c - 为什么我可以更改 const char *ptr 的内容?

转载 作者:太空狗 更新时间:2023-10-29 16:51:30 31 4
gpt4 key购买 nike

我将指针 ptr 传递给了一个函数,该函数的原型(prototype)将其作为 const

foo( const char  *str );

根据我的理解,这意味着它将无法更改传递的 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;
}

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

警告:传递“strcpy”的参数 1 会丢弃来自指针目标类型的限定符

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

main(): Its just to fill the space
foo(): ABC
main(): ABC

现在,我的问题是
1- 原型(prototype)中的const char *str 到底是什么意思?
这是否意味着函数不能更改 str 的内容?如果是这样,那么上面的程序怎么会改变这个值呢?
2-如何保证我传递的指针内容不会被改变?

上述问题中的“指针的内容”,我的意思是“指针指向的内存的内容”,而不是“指针中包含的地址”。

编辑

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

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

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

main(): Its just to fill the space
foo(): Tim
main(): Its just to fill the space

显然,str 指向的内存被更改为包含 "Tim" 的内存位置,而它在 foo() 中。虽然我这次没有使用strcpy()
const 不应该阻止它吗?还是我的理解有误?

在我看来,即使使用 const,我也可以更改内存引用和内存引用的内容。那有什么用呢?

你能给我一个例子吗?编译器会给我一个错误,告诉我我正在尝试更改一个 const 指针?

感谢大家的时间和努力。

最佳答案

你的理解是正确的,const char* 是一个契约,意味着你不能通过这个特定的指针改变内存。

问题是 C 在类型转换方面非常松懈。 strcpy 接受一个指向非常量 字符的指针,它是隐式const char* 转换为char*(正如编译器告诉你的那样)。您可以轻松地传递一个整数而不是指针。因此,您的函数无法更改 ptr 指向的内容,但 strcpy 可以,因为它看到一个非常量指针。你不会崩溃,因为在你的例子中,指针指向一个足够大小的实际缓冲区,而不是只读字符串文字。

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

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

扩展问题的答案

您正在将字符串文字分配给非常量字符,不幸的是,这在 C 甚至 C++ 中都是合法的!它被隐式转换为 char*,即使通过该指针写入现在会导致未定义的行为。这是一个已弃用的功能,目前只有 C++0x 不允许这种情况发生。

话虽如此,为了停止更改指针自身,您必须将其声明为指向 char 的常量指针 (char *const)。或者,如果您想使其指向的内容和指针本身都不会改变,请使用指向 const char 的 const 指针 (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 */
}

对于所有错误行,GCC 都会给我“错误:只读位置的分配”。

关于c - 为什么我可以更改 const char *ptr 的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3228664/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com