将const指针定义为const字符串

时间:2009-11-20 08:42:19

标签: c coding-style

乌尔里希·德雷珀(Ulrich Drepper)的一个令人讨厌的沼泽地,遇到了两个看起来很混乱的条目。

first one (全局空间中的字符串)中,Ulrich声明该字符串应定义为:

const char _pcre_ucp_names[] = "blabla";

虽然已经在 second one (函数中的字符串),但他认为应该声明为:

static const char _pcre_ucp_names[] = "blabla";

你能解释为什么更好的名字来解析一个字符串?

UDP:

首先,我删除了C ++标记 - 这个问题对C和C ++都有效。所以我不认为解释类/函数/文件范围中的静态意义的答案是相关的。

在回答之前阅读文章。文章涉及内存使用 - 存储实际数据(在.rodata或.data部分),字符串应该重新定位(如果我们谈论unix / linux共享对象),是否可以更改字符串与否。

UDP2 第一个中,表示对于全局变量的形式:

(1) const char *a = "...";

不如

(2) const char a[] = "..."

为什么呢?我一直认为(1)更好,因为(2)实际上复制了我们分配它的字符串,而(1)只指向我们分配的字符串。

5 个答案:

答案 0 :(得分:9)

这取决于 - 如果您需要字符串对项目中的其他源文件可见,则无法声明它static。如果您只需要从定义它的文件中访问它,那么您可能想要使用static

你提到的博客文章是在谈论不同的东西:

#include <stdio.h>
#include <string.h>
int main(void)
{
  const char s[] = "hello"; /* Notice this variable is inside a function */
  strcpy (s, "bye");
  puts (s);
  return 0;
}

在这种情况下,static意味着不同的东西:这会创建一个变量,该变量会持续多次调用同一个函数。他的另一个例子显示了一个函数之外的全局变量。

修改

要澄清一下,既然您编辑了问题,那么您不想使用const char *a = "string"的原因是您创建了一个额外的可写指针。这意味着,虽然您无法更改字符串的字符,但您仍然可以使指针指向完全​​不同的字符串。见下文:

const char *hello = "hello";

int main( int argc , char const *argv[] )
{
    hello = "goodbye";
    puts(hello);
    return 0;
}

该示例编译并运行。如果hello应该是常量,那肯定不是你想要的。当然,您也可以写下这个来解决这个问题:

const char * const hello = "hello";

你仍然有两个变量,你只需要一个 - hello是一个指向字符串常量的指针,如果它是一个数组,那么就没有那个额外的指针。

答案 1 :(得分:2)

声明它static表示(如果在全局,文件级别)它将在此转换单元外部不可见,或者(如果在作用域内)它将在作用域的执行之间保留其值。它与数据的“常量”无关。

答案 2 :(得分:2)

虽然这确实是一个const字符串,但它既不是指针也不是const指针,也不是第二个是声明。

两个定义(并初始化)一个常量的数组字符。

唯一的区别是第一个将是可见的并且可以从其他翻译单元访问(假定适当的声明),而第二个不会。

请注意,在C ++中,您可以将它们放入未命名的命名空间,而不是创建变量和常量static。然后,它们也无法从其他翻译单元访问。

答案 3 :(得分:1)

const char *abc = "..."; and <br/>
const char def[] = "..."

问题的一部分......

我所知道的唯一区别是,在使用sizeof运算符时,数组样式定义不会降级为指针。

sizeof(abc) == size of pointer type <br/>
sizeof(def) == size of string (including \0)

答案 4 :(得分:0)

是在全局(文件)级别,类或函数内使用?静态的含义不同..

对于文件级别:它取决于您想要的范围(全局或仅限于文件)。没有其他区别。

对于一个课程:如果你不打算改变它,最好使用静态。因为const仍然可以在构造函数上重新定义,所以如果它不是静态的,它必须为类本身内的指针分配空间。如果它是静态的,那么每个类中都不需要指针。

对于一个功能:我认为并没有真正改变任何重要的东西。在非静态情况下,指针将在堆栈上分配,并在每次函数调用时初始化为指向.rodata。在另一种情况下,它更像是一个全局变量,但范围有限。