2015-08-23 57 views
1

如果您有一個靜態常量字符串,則其用法可能會導致編譯器的解釋不一致。例如,在這種情況下:ObjC三元運算符和常量字符串

const NSString* kUntitled = @"Untitled"; 

NSString* title = kUntitled; 

編譯器會抱怨分配一個const指針非const一個(「丟棄限定符」)和可能正確的。這可以通過不使用const所有,或通過調用kUntitled.copy來解決(我有點不喜歡的類型轉換(NSString*)kUntitled的想法)

但是,如果你有來代替:

NSString* title = aTitle ?: kUntitled; 

那麼編譯器不抱怨。

我的第一個問題是,第一個例子中的警告可以忽略嗎?在將const NSString分配給非const類型時,是否存在潛在的危險?

其次,爲什麼編譯器會忽略三元運算符的情況?

+1

你也可以這樣做:'NSString const * title = kUntitled;'。我個人不會忽視任何警告。第二種情況可能只是編譯器本身的限制。 – Adam

+0

在我的情況'title'是一個成員,我不能聲明它爲const。實際上,將一個const分配給另一個幾乎沒有任何意義。 – mojuba

+0

將const指定給另一個const在方法中非常有用。但在你的情況下,我只是複製字符串。 – Adam

回答

2

歡迎古怪和C聲明的奇妙世界 - 的東西,問答題;-)

const NSString* kUntitled = @"Untitled"; 

您可能還沒有寫你打算在這裏。這定義了kUntitled是一個可變指向「常量」字符串的指針 - 通常稱爲「指向常量的指針」...然而,由於常見的「指向常量」的原因,它是「常量」實際上是「只讀指針」這意味着你可以閱讀,但不通過指針寫,什麼是指向很可能是可變的,但是它通過這個點,如果這樣是不是可變...

困惑?以上所有的意思是,你可以在以後寫:

kUntitled = @"oops you probably thought you couldn't assign"; 

由於指針本身是可變的,所以可以改變指向其他的東西。

什麼你可能打算是:

NSString * const kUntitled = @"Untitled"; 

這裏聲明瞭一個恆定指向字符串的指針 - 它是指針本身不能這麼改:

kUntitled = @"this will produce a compile error, can't change a constant"; 

如果您使用這個版本的聲明,那麼你不會得到你的作業錯誤:

NSString* title = kUntitled; 
NSString* title = aTitle ?: kUntitled; 

但是仍然留下的,爲什麼你沒有得到第二誤差與原申報的問題...

轉讓的RHS,aTitle ?: kUntitled實際上是有效的,怪異再來一次C的世界。這個表達式只是aTitle ? aTitle : kUntitled的簡寫和C運算符中這個運算符的規則,第二個和第三個參數可以是相同的基本指針類型,您的情況爲NSString *,但在限定符中有不同,您的情況爲const,結果類型是基本指針類型,其中全部爲兩個操作數的限定符。

換句話說,該表達式的結果被視爲const NSString *。這意味着你應該得到與第一次作業相同的警告。

看來,編譯器處理操作,就好像將所得的類型是基指針類型與沒有或僅有公共限定符兩個操作數的 - 即定義的相反

因此對於第二個問題,您可能發現了一個編譯器錯誤,您應該將其報告給Apple(bug reporter.apple.com)並查看他們的說法。

HTH

+0

好的三元條件運算符的類型規則的覆蓋範圍!我不知道那件事。 –

2

該警告是const NSString * kUntitled不正確的事實的副作用。這是一個指向只讀指令的聲明 - NSString。注意「只讀」的位置 - 它指的是字符串,而不是指針。但ObjC對象永遠不會只讀,從不const。你可能會說,字面NSString s 當然是,但這是implementation dependent,甚至在某些運行時環境中可以修改。

因此,您永遠無法在其他地方正確指定此對象(除非該變量也是指向const對象的指針)。

,你應該使用聲明NSString * const kUntitled - 這是「只讀指針-TO-NSString」,即指針不能改變另一個對象指向。