[英]Is there a difference between const char * const and const char []?
[英]Difference between char* and const char*?
有什么区别
char* name
它指向一个常量字符串文字,并且
const char* name
char*
是一个指向可变字符/字符串的可变指针。
const char*
是指向不可变字符/字符串的可变指针。 您不能更改此指针指向的位置的内容。 此外,当您尝试这样做时,编译器需要给出错误消息。 出于同样的原因,不推荐从const char *
转换为char*
。
char* const
是一个不可变指针(它不能指向任何其他位置),但它指向的 location 的内容是可变的。
const char* const
是指向不可变字符/字符串的不可变指针。
char *name
您可以更改name
指向的字符,以及它指向的字符。
const char* name
您可以更改
name
指向的字符,但不能修改它指向的字符。
更正:您可以更改指针,但不能更改name
指向的字符( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx ,请参阅“示例”)。 在这种情况下, const
说明符适用于char
,而不是星号。
根据 MSDN 页面和http://en.cppreference.com/w/cpp/language/declarations , *
之前的const
是 decl-specifier 序列的一部分,而*
之后的const
是声明符的一部分。
声明说明符序列后面可以跟多个声明符,这就是为什么const char * c1, c2
c1
声明为const char *
并将c2
声明为const char
。
编辑:
从评论中,您的问题似乎是在询问指针指向字符串文字时两个声明之间的区别。
在这种情况下,您不应修改name
指向的字符,因为它可能导致Undefined Behavior 。 字符串文字可以在只读内存区域(实现定义)中分配,并且用户程序不应以任何方式修改它。 任何这样做的尝试都会导致未定义行为。
所以在这种情况下(与字符串文字一起使用)的唯一区别是第二个声明给了你一点优势。 如果您尝试在第二种情况下修改字符串文字,编译器通常会向您发出警告。
#include <string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[] = "Sample string";
strcpy(str1,source); //No warning or error, just Undefined Behavior
strcpy(str2,source); //Compiler issues a warning
return 0;
}
输出:
cc1:警告被视为错误
prog.c:在函数“main”中:
prog.c:9:错误:传递“strcpy”的参数 1 会丢弃来自指针目标类型的限定符
请注意,编译器会针对第二种情况发出警告,但不会针对第一种情况发出警告。
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)
constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error
constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok
// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";
lcharp[0] = 'X'; // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error
// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X'; // compile error
((char*)astr)[0] = 'X'; // ok
在这两种情况下,您都不能修改字符串文字,无论指向该字符串文字的指针是声明为char *
还是const char *
。
但是,不同之处在于,如果指针是const char *
则编译器必须在您尝试修改指向的值时给出诊断信息,但如果指针是char *
则不会。
情况1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
上面将 str 设置为指向硬编码在程序二进制图像中的文字值“Hello”,在内存中标记为只读,这意味着此字符串文字的任何更改都是非法的,并且会引发分段错误。
案例2:
const char *str = "Hello";
str[0] = 'M' //Compile time error
案例3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
问题是两者有什么区别
char *name
它指向一个常量字符串文字,和
const char *cname
即给定
char *name = "foo";
和
const char *cname = "foo";
2之间没有太大区别,两者都可以看作是正确的。 由于 C 代码的长期遗留,字符串文字具有char[]
类型,而不是const char[]
,并且有许多旧代码同样接受char *
而不是const char *
,即使它们不接受修改参数。
两者的主要区别通常是*cname
或cname[n]
将计算为const char
类型的左值,而*name
或name[n]
将计算为char
类型的左值,它们是可修改的左值。 如果赋值的目标不是可修改的左值,则需要符合标准的编译器来生成诊断消息; 它不需要在分配给char
类型的左值时产生任何警告:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostic message
在任何一种情况下,编译器都不需要停止编译; 它足以为cname[0]
的赋值产生警告。 生成的程序不是正确的程序。 构造的行为是undefined 。 它可能会崩溃,或者更糟糕的是,它可能不会崩溃,并且可能会更改内存中的字符串文字。
如果你愿意,第一个你实际上可以改变,第二个你不能。 阅读有关const
正确性的信息(有一些关于差异的很好的指南)。 还有char const * name
,你不能重新指出它。
实际上, char* name
不是指向常量的指针,而是指向变量的指针。 您可能正在谈论另一个问题。
我要在这里补充一点,最新的编译器,例如 VS 2022,不允许使用字符串文字来初始化char*
。 char* ptr = "Hello";
抛出错误而const char* ptr = "Hello";
是合法的。
再举一个例子:
std::cout << typeid(2.3).name() << '\n'; // -----> prints "double" simply because
//2.3 is a double
//But the "double" returned by typeid(2.3).name() is indeed a
//const char * which consists of 'd','o','u','b','l','e'and'\0'.
//Here's a simple proof to this:
std::cout << typeid(typeid(2.3).name()).name() << '\n'; //prints: "const char *"
const char* charptr
charptr = typeid(2.3).name();
std::cout << charptr[3]; // ---------> prints: "b"
(我正在使用typeinfo库: http ://www.cplusplus.com/reference/typeinfo/type_info/name)
//Now let's do something more interesting:
char* charptr2="hubble";
strcpy(charptr, charptr2); // --------> Oops! Sorry, this is not valid!
您可以运行它,并为自己找到更好的东西。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.