何时使用const char *,何时使用const char[]

When to use const char * and when to use const char []

本文关键字:何时使 const char      更新时间:2023-10-16

我知道它们是不同的,我知道它们是如何不同的,我阅读了所有我能找到的关于char*char[]的问题

但是所有这些答案都没有告诉我们什么时候应该使用它们。

我的问题是:

什么时候使用

const char *text = "text";

和什么时候使用

const char text[] = "text";

有什么指导方针或规则吗?

举个例子,哪个更好:

void withPointer()
{
    const char *sz = "hello";
    std::cout << sz << std::endl;
}
void withArray()
{
    const char sz[] = "hello";
    std::cout << sz << std::endl;
}

(我知道std::string也是一个选项,但我特别想知道char指针/数组)

两者都明显不同,首先:

  1. 第一个创建一个指针。
  2. 第二行创建一个数组。

请继续阅读以获得更详细的解释:

数组版本:

char text[] = "text"; 

创建一个足够大的数组来容纳字符串字面值"text",包括它的NULL终止符。数组text初始化为字符串字面值"text"。数组可以在以后修改。此外,即使在编译时也知道数组的大小,因此可以使用 sizeof操作符来确定它的大小。


指针版本:

char *text  = "text"; 

创建一个指向字符串文本"text"的指针。这比数组版本快,但是指针指向的字符串不应该被改变,因为它位于只读实现定义的内存中。修改这样的字符串字面值会导致未定义行为

实际上c++ 03不赞成使用没有const关键字的字符串字量。所以声明应该是:

const char*text = "text";

此外,需要使用strlen()函数,而不是sizeof来查找字符串的大小,因为sizeof操作符只会给您指针变量的大小。


哪个版本更好?

取决于用法。

  • 如果您不需要对字符串进行任何更改,则使用指针版本。
  • 如果你想改变数据,使用数组版本。

编辑:我刚刚注意到(在评论中),OP寻求以下之间的区别:

const char text[]const char* text

除了关于修改字符串字面值的问题,上面的不同点仍然适用。有了const限定符,数组test现在是一个包含const char类型元素的数组,这意味着它们不能被修改。

考虑到这一点,我会选择数组版本而不是指针版本,因为指针可以(错误地)很容易重置到另一个指针,并且可以通过另一个指针修改字符串,从而导致UB。

最大的区别可能是您不能对指针使用sizeof操作符来获取开始指向的缓冲区的大小,而与const char[]版本一样,您可以对数组变量使用sizeof来以字节为单位获取数组的内存占用大小。所以这取决于你想用指针或缓冲区做什么,以及你想如何使用它。

例如:

void withPointer()
{
    const char *sz = "hello";
    std::cout << sizeof(sz) << std::endl;
}
void withArray()
{
    const char sz[] = "hello";
    std::cout << sizeof(sz) << std::endl;
}

会给你非常不同的答案。

一般来说,要回答这类问题,使用最明确的

在这种情况下,const char[]胜出,因为它包含了关于内部数据的更详细的信息——即缓冲区的大小。

提醒一下:

我选static const char sz[] = "hello";。这样声明有一个很好的优点,即通过写入只读内存来更改常量字符串,从而使程序崩溃。如果没有static,丢弃constness然后更改内容可能不会被注意到。

同样,static允许数组仅仅位于常量数据部分,而不是在堆栈上创建,并在每次调用函数时从常量数据部分复制

如果使用数组,则在运行时初始化数据。如果使用指针,运行时开销(可能)更少,因为只需要初始化指针。(如果数据小于指针的大小,则数据的运行时初始化小于指针的初始化。)所以,如果你有足够的数据并且你关心初始化的运行时成本,你应该使用指针。你几乎不应该关心这些细节。

几年前我从Ulrich Drepper的博客文章中得到了很多帮助:

如此接近,但没有雪茄和更多的数组乐趣

这个博客的要点是const char[]应该是首选的,但只能作为全局变量或静态变量。

使用指针const char*有如下缺点:

    附加变量
  1. 指针可写
  2. 一个额外的间接
  3. 通过指针访问字符串需要2次内存加载

只是提一个小问题,表达式:

const char chararr[4] = {'t', 'e', 'x', 't'};