有什么区别
char* name
指向一个常量字符串字面量,和
const char* name
char *name
你可以改变name所指向的字符,也可以改变它所指向的字符。
name
const
char
*
const char * c1, c2
c1
const char *
c2
const char
编辑:
从评论来看,你的问题似乎是在问当指针指向一个字符串字面值时,两个声明之间的区别。
因此,在这种情况下(使用字符串字面值)唯一的区别是,第二个声明给了您一点优势。如果你试图在第二种情况下修改字符串字面量,编译器通常会给你一个警告。
在线示例
#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丢弃指针目标类型的限定符
cc1:警告被视为错误 prog.c:在函数main中: Prog.c:9:错误:传递' strcpy '的参数1丢弃指针目标类型
注意,编译器对第二种情况发出警告,但对第一种情况没有发出警告。
如果你想,第一个你可以改变,第二个你不能。阅读const的正确性(有一些关于区别的很好的指南)。还有char const * name,你不能重新指向它。
char const * name
实际上,char* name不是一个指向常量的指针,而是一个指向变量的指针。你可能在说另一个问题。
char * const和const char *有什么区别?< / >
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 *。
char *
然而,不同之处在于,如果指针是const char *,则编译器必须在你试图修改指向值时给出诊断,但如果指针是char *,则不会给出诊断。
char*是一个指向可变的字符/字符串的可变的指针。
char*
const char*是一个指向不可变的字符/字符串的可变的指针。不能更改此指针所指向的位置的内容。此外,当你尝试这样做时,编译器需要给出错误消息。出于同样的原因,不支持从const char *到char*的转换。
const char*
char* const是一个不可变的指针(它不能指向任何其他位置),它所指向的位置的内容是可变的。
char* const
const char* const是一个指向不可变的字符/字符串的不可变的指针。
const char* const
问题是两者之间有什么区别
const char *cname
即给定
char *name = "foo";
而且
const char *cname = "foo";
两者之间没有太大的区别,两者都可以被视为正确的。由于C代码的长期遗留,字符串字面量的类型是char[],而不是const char[],并且有许多旧代码同样接受char *而不是const char *,即使它们不修改参数。
char[]
const char[]
一般来说,这两个的主要区别是*cname或cname[n]将计算出类型为const char的左值,而*name或name[n]将计算出类型为char的左值,即修改的左值。如果赋值的目标不是一个可修改的左值;它不需要在赋值给类型为char的左值时产生任何警告:
*cname
cname[n]
*name
name[n]
name[0] = 'x'; // no diagnostics *needed* cname[0] = 'x'; // a conforming compiler *must* produce a diagnostic message
在这两种情况下,编译器都不是要求来停止编译;它为赋值给cname[0]生成一个警告就足够了。生成的程序不是正确的程序。构造的行为是未定义的。它可能会崩溃,或者更糟,它可能不会崩溃,并且可能会改变内存中的字符串文字。
cname[0]
案例1:
char *str = "Hello"; str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
上面设置str指向“Hello”字面值,该字面值是硬编码在程序的二进制图像中,在内存中被标记为只读,这意味着这个String字面值的任何更改都是非法的,并且会抛出分割错误。
案例2:
const char *str = "Hello"; str[0] = 'M' //Compile time error
案例3:
char str[] = "Hello"; str[0] = 'M'; // legal and change the str = "Mello".
我想在这里补充一点,最新的编译器,例如VS 2022,不允许char*用字符串文字初始化。char* ptr = "Hello";抛出错误,而const char* ptr = "Hello";是合法的。
char* ptr = "Hello";
const char* ptr = "Hello";