2009-11-20 27 views
2

重新挖掘了Ulrich Drepper的沼澤並遇到了看起來像是混淆的2個條目。將const指針定義爲const字符串

first one(全球空間字符串)李晶指出,該字符串應該定義爲:

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)只指向我們賦值的字符串。

+1

你可以聲明爲爲const char * X = 「布拉布拉」;它看起來更漂亮:) – 2009-11-20 08:48:08

+0

這是我也認爲正確的解決方案,但已經在「第一」Ulrich批評它 – dimba 2009-11-20 08:58:41

+0

「首先,我刪除了C++標籤 - 這個問題是有效的C以及C + +」哼。你的意思是它是「*不適用於C++」嗎?否則,你爲什麼刪除標籤?請注意,C++的答案會有所不同 - 默認情況下,C++將爲const數組提供內部鏈接。 – 2009-11-20 15:20:26

回答

7

這取決於 - 如果您需要該字符串對項目中的其他源文件可見,則不能聲明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; 
} 

這個例子編譯和運行。如果你好,應該是恆定的,這肯定不是你想要的。當然,你也可以解決這個問題寫這樣的:

const char * const hello = "hello"; 

你仍然有兩個變量,你只需要一個,但 - 你好是一個指向字符串常量,在那裏,如果它是一個數組有ISN」那個額外的指針在路上。

+0

+1表示靜態。但是,全局變量(「第一個」) - 爲什麼const char a [] i =「..」首選const char a * =「..」? – dimba 2009-11-20 09:14:17

+0

因爲'const char * a =「string」'給你留下了一個額外的不必要的指針。每次讀取該變量時,都必須經過指針 - 記住'const char *'仍然可以指向不同的字符串。 'const char a [] =「string」'避免創建額外的指針,節省空間和時間。 – LnxPrgr3 2009-11-20 15:10:03

1

聲明它static裝置(如果在全球,文件級),它不會此翻譯單元,或者(如果一個範圍內),它將保留其範圍的執行之間值外面是可見的。它與數據的「不變性」無關。

0

它是用於全局(文件)級別,還是在類內或函數內使用?靜態的含義不同。

對於文件級別:它取決於您想要的範圍(全局或受限於文件)。沒有其他區別。

對於一個班級:如果你不想改變它,最好用靜態。因爲const仍然可以在構造函數中重新定義,所以如果它不是靜態的,它將不得不爲類內部的指針分配空間。如果它是靜態的,那麼在每個類中都不需要指針。

對於一個功能:沒有真正改變我認爲重要的任何事情。在非靜態的情況下,一個指針將被分配到堆棧上,並被初始化爲在每個函數調用中指向.rodata。在另一種情況下,它更像是一個全局變量,但範圍有限。

+0

對於函數,其含義取決於函數是否是類成員。非成員靜態函數與文件作用域靜態變量類似:它們只在定義它們的文件中可見。可以調用靜態成員函數,而無需引用對象(SomeClass :: staticMember()與someObject.nonStaticMember())。 – LnxPrgr3 2009-11-20 09:00:18

1

儘管這確實是一個常量字符串,但它既不是指針也不是常量指針,也不是第二個聲明。

兩個定義(並初始化)一個常數數組的字符。

唯一的區別是第一個可見並可從其他翻譯單元(假設爲正確的聲明)訪問,而第二個不會。

請注意,在C++中,您可以將它們放入一個未命名的名稱空間,而不是製作變量和常量static。然後,他們也無法從其他翻譯單位訪問。

1

在問題的

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

部分...

據我所知,唯一的區別是使用sizeof操作符,當陣列式的定義不降級爲指針。

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