乌尔里希·德雷珀(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)只指向我们分配的字符串。
答案 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。在另一种情况下,它更像是一个全局变量,但范围有限。