char *和const char *之间的区别?
有什么区别
char* name
它指向一个常量string,和
const char* name
-
const char*
是一个不可变的字符/string的可变指针。 你不能改变这个指针指向的位置的内容。 另外,当你尝试这样做时,编译器需要给出错误信息。 出于同样的原因,从const char *
到char*
转换已被废弃。 -
char* const
是一个不可变的指针(它不能指向任何其他的位置), 但它指向的位置的内容是可变的 。 -
const char* const
是一个不可变的指向不可变字符/string的指针。 -
char*
是完全宽容的。
char *name
您可以更改name
指向的字符,以及它指向的字符。
const char* name
您可以更改 name
指向的字符,但不能修改它指向的字符。
更正:您可以更改指针,但不是 name
指向的字符( https://msdn.microsoft.com/zh-cn/library/vstudio/whkd4k6a(v=vs.100).aspx ,请参阅“示例“)。 在这种情况下, const
说明符适用于char
,而不是星号。
根据MSDN页面和http://en.cppreference.com/w/cpp/language/declarations,*之前的;const
是decl-specifier序列的一部分,而const
*
之后的const
是声明的一部分。
声明说明符序列后面可以跟多个声明符,这就是为什么const char * c1, c2
声明c1
为const char *
和c2
为const char
。
编辑:
从注释中,你的问题似乎是在指针指向一个string时,两个声明之间的区别。
在这种情况下,您不应该修改name
指向的字符,因为它可能会导致未定义的行为 。 string文字可以分配在只读存储器区域(实现定义)中,用户程序不应该修改它。 任何尝试这样做都会导致“未定义的行为”。
所以在这种情况下(string文字的使用)唯一的区别是第二个声明给你一个轻微的优势。 如果在第二种情况下尝试修改string,编译器通常会给出警告。
在线示例:
#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丢弃指针目标types的限定符
注意编译器警告第二种情况,但不是第一种情况。
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
在任何情况下,您都不能修改string文字,无论指向该string文字的指针是声明为char *
还是const char *
。
然而,不同的是,如果指针是const char *
那么编译器必须给出一个诊断,如果你试图修改指向的值,但如果指针是char *
那么它不会。
第一个你真的可以改变,如果你想,第二个你不能。 阅读关于const
正确性(有一些不错的指导差异)。 还有char const * name
,你不能重新命名它。
实际上, char* name
不是指向常量的指针,而是指向variables的指针。 你可能会在谈论这个问题。
char * const和const char *有什么区别?
问题是两者之间有什么区别
char *name
它指向一个常量string,和
const char *cname
即给出
char *name = "foo";
和
const char *cname = "foo";
2和2之间没有太大的差别,都可以看作是正确的。 由于C代码的悠久遗产,string文字有一个char[]
,而不是const char[]
,并且有许多旧代码同样接受char *
而不是const char *
,即使它们不修改参数。
2的主要区别在于, *cname
或cname[n]
将被计算为const char
types的左值,而*name
或name[n]
将被计算为char
types的左值,这是可修改的左值 。 如果赋值的目标不是可修改的左值 ,则需要符合的编译器生成诊断消息; 它不需要给char
types的左值赋予任何警告:
name[0] = 'x'; // no diagnostics *needed* cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
无论哪种情况,编译器都不需要停止编译; 它足以产生一个警告 ,分配给cname[0]
。 由此产生的程序不是一个正确的程序。 构造的行为是未定义的 。 它可能会崩溃,甚至更糟糕的是,它可能不会崩溃,并可能改变内存中的string字面值。
情况1:
char *str = "Hello"; str[0] = 'M' //No warning or error, just Undefined Behavior
上面设置str指向在程序的二进制图像中硬编码的字面值“Hello”,在内存中标记为只读,意味着此Stringstring中的任何改变都是非法的,并且会引起分段错误。
情况2:
const char *str = "Hello"; str[0] = 'M' //Compiler issues a warning
案例3:
char str[] = "Hello"; str[0] = 'M'; // legal and change the str = "Mello".
只是给一个额外的例子:
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!
你可以运行它,并为自己看到更好的东西。