2011-12-14 40 views
16

請考慮下面的代碼:的typedef指針常量的怪事

typedef struct Person* PersonRef; 
struct Person { 
    int age; 
}; 

const PersonRef person = NULL; 

void changePerson(PersonRef newPerson) { 
    person = newPerson; 
} 

出於某種原因,編譯comlaining約只讀不可轉讓的價值。但const關鍵字不應該使指針爲const。有任何想法嗎?

+2

「但const關鍵字不應該使指針爲常量。」咦?簡短的回答:不要使用typedefs,他們只是在那裏混淆你。記住他們,直到你需要他們。 – wildplasser 2011-12-14 12:29:44

+12

@wildplasser:「不要使用typedefs」不是很好的建議。也許「不要隱藏在typedef後面的指針」更合適...... – 2011-12-14 12:32:08

+1

我不同意。它*是一個很好的建議。隱藏typedef後面的結構與隱藏指針一樣令人困惑。它只會污染你的精神命名空間。即使沒有語法突出顯示,我更容易和更快地讀「struct person * p」,然後「pPerson p」。 – wildplasser 2011-12-14 12:36:53

回答

33

注意

typedef int* intptr; 
const intptr x; 

是不一樣的:

const int* x; 

intptr是指向int的指針。 const intptr是指向int的常量指針,而不是指向常量int的指針。

因此,在一個typedef指針後,我不能使它對內容的const?

有一些醜陋的方式,比如gcc的typeof macro

typedef int* intptr; 
intptr dummy; 
const typeof(*dummy) *x; 

,但是,你看,這是毫無意義的,如果你知道背後intptr類型。

5
const PersonRef person = NULL; 

struct Person*const person= NULL; 

所以你consting指針,而不是對象。

0

你在聲明

person = newPerson; 

獲取和錯誤

error: assignment of read-only variable ‘person’ 

,因爲你已經聲明者爲const因此其價值只能只讀.... 常量的值不能改變

如果你要改變那個vatiable那麼你爲什麼要把它作爲const?

刪除const關鍵字您的代碼將工作正常

1

永不隱藏指針的typedef的背後,則是真的不好的做法,只會創建錯誤。

一個這樣臭名昭着的bug是被聲明爲const的typedef:ed指針類型將被視爲「指向非常數數據的常量指針」,而不是「指向常數數據的非常數指針」,它是人們直覺上期望的是什麼。這是你的程序中發生的事情。


解決方案:

typedef struct 
{ 
    int age; 
} Person; 

const Person* person = NULL; // non-constant pointer to constant Person 
3

雖然問題已經被解決了答案上面,我很想念......的原因

因此,也許作爲一個經驗法則:

  1. const總是指它的前身令牌。
  2. 如果沒有這樣的情況,它就是「強制」它的後繼標記。

這個規則可以真正幫助你聲明一個指向const指針的指針或者其他東西。

無論如何,考慮到這一點,就應該得到清楚爲什麼

struct Person *const person = NULL; 

聲明瞭一個常量指針的可變結構。

想想看,你的typedef 「groups」struct Person與指針標記*。 所以,寫

const PersonRef person = NULL; 

你的編譯器看到的是這樣的(僞代碼):

const [struct Person *]person = NULL; 

由於沒有什麼const的離開,它deklares令牌它是正確的struct Person *不變。

嗯,我想,這就是爲什麼我不喜歡通過typedefs隱藏指針,而我喜歡typedefs這樣的。那寫什麼

typedef struct Person { ... } Person; 
const Person *person; /*< const person */ 
Person *const pointer; /*< const pointer to mutable person */ 

它應該是很清楚的編譯器和人類,你在做什麼。