2015-02-23 51 views
2

它是安全的環比Objective-C的布爾值將像這樣:循環在布爾值將在Objective-C

for (BOOL flagA = NO; flagA <= YES; flagA++) 
    for (BOOL flagB = NO; flagB <= flagA; flagB++) 
     // ... 

我想通過標誌的所有相關排列在XCTestCase使用這種循環。

但它看起來好像YES++仍然YES至少在某些平臺上(因此導致一個無限循環例如在iPhone 6 Plus上的模擬器),而我本來預計BOOL也只是被視爲int(因此YES++成爲2)。

我是否必須通過int s(我最好的猜測)來代替,還是可以通過某種方便的方式來挽救BOOL的使用?

+1

爲什麼你不使用整數然後使用整數作爲布爾值? – Sulthan 2015-02-23 09:34:24

+0

@Sulthan請參閱Q中的最後一行。那麼這是要走的路嗎?你知道爲什麼'BOOL'(顯然)在不同平臺上的工作方式不同(用'++'來說)? – Drux 2015-02-23 09:35:54

+0

我目前不能在代碼中看到一個錯誤,因爲'YES'應該是1,'NO'應該是0,'BOOL'應該是有符號字符的,但是你不應該用'<='比較布爾值或者增加布爾值。這些操作是未定義的。 – Sulthan 2015-02-23 09:39:02

回答

4

你們都缺少點這裏。 Drux詢問爲什麼他不能通過BOOL遞增,而它應該是一個字符(8位值),它是完美遞增的。

答案很簡單。 BOOL有時是一個字符,有時候是一個bool,具體取決於目標。從objc.h文件:

#if !defined(OBJC_HIDE_64) && TARGET_OS_IPHONE && __LP64__ 
typedef bool BOOL; 
#else 
typedef signed char BOOL; 

如果我們通過遍歷bool你會得到1最大的價值。

編輯:

能否請您加入到指定+ +的布爾語義的參考? - Drux

儘管這bool必須是8位的最小值,也不能有超過01任何其他值。爲什麼?由於bool a = 3(布爾等號運算符)將3轉換爲bool值,即true1

所以bool a = true; a++相同bool a = 2;這使得a1

+0

我們並沒有錯過任何一點。我們告訴他,他在做什麼沒有定義。 – Sulthan 2015-02-23 09:50:40

+1

但你沒有告訴他爲什麼。 – 2015-02-23 09:51:04

+0

原因不在於實際的宏實現,原因在於它背後的邏輯。這是一個布爾值,所以沒有定義增量。這是一個布爾值,所以沒有定義比較。 – Sulthan 2015-02-23 09:52:22

0

我覺得@Sulthan意味着這樣的事情(做過於明確的故意):

for(int indexA = 0; indexA <= 1; indexA++){ 
    for(int indexB = 0; indexB <= indexA; indexB++){ 

     BOOL flagA = (indexA == 1) ? YES : NO; 
     BOOL flagB = (indexB == 1) ? YES : NO; 

     // Use your flags (booleans) here... 

    } 
} 

(當然,你可以代替Objective-C的布爾值只使用int S,如果你想以避免使用太多冗餘變量)。

附錄:我實際上執行的 「跳轉到」 在Xcode(OSX項目),以及部分看起來是這樣的:

#if __has_feature(objc_bool) 
#define YES __objc_yes 
#define NO __objc_no 
#else 
#define YES ((BOOL)1) 
#define NO ((BOOL)0) 
#endif 

(usr/include目錄/ objc/objc.h)

不能「跳轉到」上__objc_yes(賦予「找不到符號」)

+0

但爲什麼是SG。這樣甚至有必要?是不是'BOOL'只是映射到某種類型('unsigned char'可能),表示多於1位? – Drux 2015-02-23 09:41:28

+0

至少,我會避免使用布爾變量作爲循環變量,因爲它會混淆一些必須維護代碼的人(這不是人們習慣看到的東西)。 – 2015-02-23 09:41:44

+0

我知道你的意思,但我認爲這是依賴於實現並且有些不能保證。如果我記得正確,'true'只需要是「非零」,不一定是1(我可能是錯的)。 – 2015-02-23 09:42:46

0

我看到會被添加在循環中斷逃避無限循環的唯一方法。

另一種可能性是使用簡單的整數和停止的循環時,counter == 2

for (BOOL flagA = NO; YES; flagA++) { 
    for (BOOL flagB = NO; YES; flagB++) { 
     // Do something 
     if (flagB) 
      break; 
    } 
    if (flagA) 
     break; 
} 
+0

是的,即使'BOOL's也可以工作。 (雖然我寧願在這種情況下循環遍歷int,在這種情況下,這些休息是IMO冗餘的。) – Drux 2015-02-23 09:45:20

+0

@Drux是的,我可能也會這樣。但是因爲問題是要找到一種使用'BOOL'的方法,我只是回答了我看到的唯一可能性。 – KIDdAe 2015-02-23 09:46:32

+0

Thx,非常感謝。 – Drux 2015-02-23 09:47:03

0

的值。如果你超過BOOLs操作,然後代替設置:

for (BOOL flagA = NO; flagA <= YES; flagA++) 
    for (BOOL flagB = NO; flagB <= flagA; flagB++) 
     // ... 

你真正應該做的事情這(雖然它不是你想要的):

for (BOOL flagA = NO; flagA != YES; flagA = !flagA) 
    for (BOOL flagB = NO; flagB != flagA; flagB = !flagB) 
     // This is the only safe way to 'iterate' BOOLs 

beh aviour,(BOOL)++沒有明確定義*因爲BOOL只能是YESNO。你真正應該做的是將你的BOOL轉換爲int,然後遍歷它,或者完全重構你的循環以使用int類型。

與您鑄造BOOLints的問題是,正如你所指出的那樣,BOOL被typedef定義的東西,只有8的信息*位,所以它纔有意義有255次迭代。實際上,在更近的時候,BOOL根本不可鑄造,因爲它被定義爲編譯器固有的(objc_bool,它可以具有值__objc_yes__objc_no)。 __objc_no++沒有意義。我的(強烈的)建議是重構你的代碼,所以你在遍歷整數,並且在每次迭代中檢查BOOLs。無論您是使用BOOL值,還是重構您的循環都取決於您,但是以您指示的方式重複使用BOOL值的方式都不安全,並且(現在因爲這一點)不受支持。


*在過去幾年中,BOOL實現細節是顯而易見的(即強制轉換爲unsigned char類型)。隨着編譯器內在函數的出現,細節被隱藏(儘管它們可能是相同的)。他們現在被隱藏的原因是因爲你真的不應該依賴它們,而阻止依賴它們的人的最簡單方法是將它們完全隱藏在編譯器中。

+0

爲什麼你認爲第二個版本不是我想要的?我看起來很好。 (雖然我同意循環遍歷'int's是更好的選擇)。 – Drux 2015-02-23 09:57:01

+0

看來,這個循環你甚至不會輸入一次。 flagA == flagB在第二次循環的第一次迭代中,然後flagA == YES,並且不會再次輸入第一個循環。 – KIDdAe 2015-02-23 09:59:29

+0

@KIDdAe我現在看到。謝謝。 – Drux 2015-02-23 10:02:54