为什么我能够修改这个const char*数组?
为什么我能够修改这个const char*数组?
在C/C++中,const关键字用于声明常量,用于表示一个不可修改的值。通常情况下,const修饰的是它左边的内容。但是,在类型声明中,const修饰的是它右边的内容。
比如,下面的两个声明是等价的:
int const *i1; const int *i2;
它们都定义了指向一个const int的指针。你可以修改i1和i2指针的指向,但是不能修改它们所指向的值。
但是,对于下面这种声明:
int *const i3 = (int*) 0x12345678;
它定义了一个指向整数的const指针,并将其初始化为指向内存地址12345678。你可以修改地址12345678处的整数值,但是不能修改i3指针所指向的地址。
回到最初的问题,为什么我能够修改const char*数组?
在C/C++中,字符串常量被解释为一个指向字符数组的指针。而在声明const char*数组时,const修饰的是指针所指向的值,即字符的类型。所以,const char*声明的数组是一个指向const字符的指针,你不能修改指针所指向的字符的值。
然而,在实际使用中,我们可以通过其他方式修改const char*数组的值。这是因为编译器在编译过程中会将字符串常量存储在只读段,这个只读段在内存中是只读的,但是在某些平台上,通过一些技巧,我们仍然可以修改这个只读段的值。这是一种不安全的行为,不建议在实际开发中使用。
总结一下,我们能够修改const char*数组的原因是编译器将字符串常量存储在只读段,而不是在可写段。为了避免这种不安全的行为,我们应该尽量避免修改const char*数组的值,以免引起未定义的行为。在实际开发中,如果需要修改字符串的值,应该使用char数组或std::string类来声明字符串变量。
为了避免混淆,总是将const限定符添加在左边。
"为了避免混淆"对我来说并没有解释混淆是什么。
实际上,这是我在SO上找到的关于这个问题的最好的答案。
作为一种代码规范,我很少遇到这种风格,所以不太可能采用它。然而,作为一种学习工具,这个答案非常有帮助!(所以我猜这种风格不太常见。)
不同意,将const应用于跟随它的事物会更一致。在第一个const的情况下,是int数据是常量。在第二个const的情况下,是p-实际的指针变量是常量。将const应用于*而不是p是没有意义的,所以我们应该真正地在前面添加const以避免混淆。
p与类型(const int *const)没有关系。无论好坏(如果你问我),const限定符在C和C++中都是后缀的:cf const成员函数void foo(int a) const;。声明const int的可能性是例外而不是规则。
我不确定const类型限定符是“意味着”后缀的。毕竟,你不会将其他类型限定符(如volatile和restrict)后置,那么为什么const要这样呢?至于const成员函数,它不适用于C,在C++中成员函数确实有后缀的specifier和modifier,包括const、override、final等。但这些不是类型限定符(尽管对于const使用的关键字确实是相同的),所以这些规则不一定适用于类型声明。
实际上,const在成员函数上限定了一个类型:隐式this指针的类型,因此也是函数的类型。restrict只限定指针,所以它最终位于*的右边,我更喜欢volatile后置。
"将所有类型限定符写在它们修改的左边" - 这种方法并不总是奏效。我有99%的把握,像int unsigned typedef foo;这样的东西是无效的。什么?这实际上有效吗?echo "int unsigned typedef foo_t;" | gcc -c -xc - -o /dev/null没有生成编译器错误。该死,C的类型系统非常一致。
我一定是在想static,它是一种存储说明符,而不是类型限定符。
按照上述建议编写声明的另一个好处是,对于每个const单词的实例,const限定的类型是单词左边的所有内容,而const限定的对象是单词右边的所有内容。
一个遗漏的部分:整个评论讨论表明,我们完全可以自由决定采用何种顺序,好像这在std中没有定义,编译器尚未编写!:) 那么,到底是什么让我们有这种根据自己的风格偏好随意放置const的自由呢?(显然不完全正确,但“大多数”是,这就不应该是显而易见的了...例如,这个答案试图解释,但仍然不令人百分百满意。)
为什么我能修改const char*数组?
问题的出现原因是const char*和char* const之间的区别。前者是指向const char的指针,后者是指向char的常量指针。前者指向的值不能改变,但指针可以改变;后者指向的值可以改变,但指针本身不能改变(类似于引用)。还有一种const char* const,它是指向常量char的常量指针(因此它的任何部分都不能改变)。
解决方法是使用合适的声明语法来定义变量。要声明指向常量char的指针,应使用const char*;要声明常量指针,应使用char* const;要声明指向常量char的常量指针,应使用const char* const。此外,还应避免在同一声明中定义多个变量,以避免混淆。
- const char*是指向const char的指针,const char*数组中的值可以改变。
- char* const是指向char的常量指针,char* const数组中的值不能改变。
- const char* const是指向常量char的常量指针,const char* const数组中的任何部分都不能改变。
注意:const char*和char const*是等效的,但最好使用char const来保持const的位置与指针const的位置相同。
最后,要声明多个变量,最好分开声明,以避免混淆。大多数编码规范也明确禁止在同一行上定义多个变量。
对于const char* const*的情况,这是指向const char*的指针的指针。即指针指向了一个指向const char的指针。