繁体   English   中英

char* 和 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 * ,即使它们不接受修改参数。

两者的主要区别通常是*cnamecname[n]将计算为const char类型的左值,而*namename[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不是指向常量的指针,而是指向变量的指针。 您可能正在谈论另一个问题。

char * const 和 const char * 有什么区别?

我要在这里补充一点,最新的编译器,例如 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM