将const指针定义为const字符串

乌尔里希·德雷珀(Ulrich Drepper)的醉酒,看到了两个看似令人困惑的参赛作品。

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

const char _pcre_ucp_names[] = "blabla"; 

虽然已经在第二个 (函数中的字符串),他认为它应该声明为:

 static const char _pcre_ucp_names[] = "blabla"; 

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

UDP:

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

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

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

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

不太好

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

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

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

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

 #include  #include  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是一个指向字符串常量的指针,如果它是一个数组,那么就没有那个额外的指针。

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

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

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

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

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

 const char *abc = "..."; and 
const char def[] = "..."

部分问题……

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

 sizeof(abc) == size of pointer type 
sizeof(def) == size of string (including \0)

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

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

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

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