char * const和const char *有什么区别?(重复-需要更多澄清)

3
所以这仅仅是一个重复的问题: char * const 和 const char * 有什么区别? 两者有什么不同:
char * const 

并且

const char *

但我仍然不明白。
所以,根据第一个答案:
const char *是指向const char的指针,而char * const是指向char的常量指针。
前者指向的值不能更改,但指针可以更改。后者指向的值可以更改,但指针不能更改(类似于引用)。
好的,所以,我已经编写了以下代码:
//exercises
char* barfoo = "variable_test";

const char* my_pointer_to_const_char = barfoo; //"barfoo" can't be changed but the pointer to it, can!

barfoo = "changed!";
std::cout<< barfoo << std::endl;

根据上面的回答,barfoo无法更改? 但我在我的代码中已经将其更改,并打印了“更改”。我不明白难道它不应该抛出错误吗? 请给我一个正确的示例,因为我显然做错了什么。

为什么barfoo不能被改变?它是一个非const指向非const字符的指针。你创建了一个指向它原始值的const指针并不相关。 - Dave Newton
因为:“首先,指针所指向的值是不能被改变的,但指针本身是可以改变的。”barfoo 是被指向的值,对吧? - Trt Trt
这是一个不同的引用。 - Dave Newton
添加一行代码 std::cout<< my_pointer_to_const_char << std::endl; 并查看结果。 - Neb
1
barfoo 是一个指针,它可以被改变,在这个例子中它不是常量!你应该看到 my_pointer_to_const_char - Ali Sepehri-Amin
2
如果您不理解重复问题中的某个答案,可以在那里的评论中请求澄清。我们真的不需要另一篇关于const位置的帖子。 - StoryTeller - Unslander Monica
2个回答

4
你对于理解缺少两个关键概念。
一个是指针,另一个是指针所指向的“东西”。它们是两个独立的“事物”。指针本身和指针所指向的任何内容。这是第一个关键概念。
第二个关键概念是其中之一或双方都可以是const。无论哪一个是const,都不能被更改。
如果指针本身是const,则无法更改指针。它将始终指向相同的“东西”,直到指针超出范围并被销毁。但是,即使指针是const,您也可以使用该指针来修改其“东西”,除非“东西”本身是const
如果指针是指向const“东西”的指针,则无法使用此指针更改“东西”。但是,您可以更改指针以指向不同的const“东西”。
或者,即使指针据称是指向const“东西”的指针,如果有另一个指针指向相同的“东西”,而且另一个指针可能不一定是指向const“东西”的指针;它可以是非const指针。在这种情况下,其他指针可以用于更改相同的“东西”(因为毕竟它不是指向某个const的东西)。现在,即使第一个指针是指向const的东西的指针,它所指向的const东西现在已经更改了。这导致了有关别名规则的深奥讨论,最好留到以后再说...
但是,回到手头的主题:
char* barfoo = "variable_test";

const char* my_pointer_to_const_char = barfoo; //"barfoo" can't be changed but the pointer to it, can!

barfoo = "changed!";

在这里,你改变了其中一个指针本身,并没有改变指针所指向的内容。字面字符串“variable_test”仍然“存在”,无论那个“存在”在哪里,而且const指针仍然指向它。对一个指针做的任何事情都不会影响另一个指针。它们是不同的“东西”。
你需要进行轻微的心理转变。你需要清楚地将指针本身与指针所指向的任何内容分开。

这导致了一个关于别名规则的神秘讨论,最好留到其他时间再进行...哈哈,好玩!无论如何,非常感谢你的答案!它帮了我很大的忙! - Trt Trt
就像你所说的,“字面字符串“variable_test”仍然存在”,我该如何找到它并进行更改?我可能听起来很愚蠢,但我想要一个例子,其中IDE或编译器告诉我无法更改它,因为它是常量。 - Trt Trt
字面字符串在定义上是 const 的。编译器可以允许你将其分配给 char *,并给出警告。你可能能够编译修改它的代码。这个代码可能运行而不会崩溃。但仍然是未定义的行为。 - Sam Varshavchik

0

我们知道指针存储着它们操作数的地址值。

例如,如果char *ptr=a,那么ptr将存储变量a的地址。同时,任何被定义为常量的变量都不能改变其值。如果const int a=5,那么像a++这样的语句是无效的,因为这会更改已被禁止的a的值。

同样地,如果一个指针ptr指向常量整数a并且声明为const int *ptr=a,那么像ptr=b这样的语句也是无效的,因为ptr不能指向b,因为它是一个指向常量的指针,指向a

了解了这些,常量和指针之间有两种组合。

类型1:指向常量的指针

const int a=5;
int* const ptr=a;

在这种情况下,变量是一个常量,其值无法修改。 假设a的内存地址为0x9978。由于指针存储变量的地址,ptr=0x9978
分析以下语句:-
a=6; //Invalid: Value of a cannot be changed
*ptr=9; //Invalid: *ptr refers to a and will change its value. 
int b=t;
ptr=b;//Valid: ptr is not constant and can point anywhere

希望这个概念现在清晰了。

类型2:常量指针

在这里,指针是常量。一旦它指向一个变量,就不能指向任何其他变量。它在其生命周期内存储一个常量地址。

int a=7;
const int* ptr=a;

这里无法修改ptr(0x9978)的值。 再次查看语句:

a=6; //Valid: Value of a can be changed
*ptr=9; //Valid: *ptr refers to a and its value can be altered. 
int b=t;
ptr=b;//InValid: ptr is constant and cannot point anywhere else.

因此,ptr现在不能指向任何其他变量。
回到你的问题,为了更好地理解,将char *视为字符串类型(字符缓冲区)的变量,而不是指针!

char* barfoo = "variable_test"; //barfoo is a string storing 'variable_test'
const char* my_pointer_to_const_char = barfoo; 
// This is type 2, constant pointer. Thus, my_pointer_to_const_char cannot 
//point to any other variable and will always store the address of barfoo
barfoo = "changed!";
//this is perfectly valid as this statement will alter the value of string 
//barfoo. my_pointer_to_const_char will still store the address of barfoo.

如果仍有任何疑问,请随意评论 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接