3

I read Mike Ash's Objective-C pitfalls page, and now I'm paranoid about implicitly casting variables of type id to BOOL.

Assume I have a 'dangerous' pointer with the lower bits zeroed out, so that casting it to a BOOL would produce NO even though it points to a valid object. Let's call this 'dangerous' pointer foo.

How do simple if statements work? Does the if statement cast foo to a BOOL when it evaluates the condition? Or does it cast to a pure boolean?

if( foo )
{
  [myArray addObject:foo];
}

Does it work the same way in ternary expressions?

// Does this break when foo is 'dangerous'?
self.titleLabel.hidden = foo ? YES : NO ; 

Or will the ternary only break if I do this:

// I'm pretty sure it breaks now
self.titleLabel.hidden = ((BOOL)foo) ? YES : NO ; 

I feel like I'm missing something basic about logical operations in C, and how they relate to BOOL. Please help enlighten me.

4

2 に答える 2

8

Objective-C が暗黙的に BOOL にキャストするのはいつですか?

この句は意味的に正しくないため、決して使用しないでください。キャストは、定義上、明示的です。あなたが求めているのは、「暗黙の型変換」と呼ばれるものです (強制 - ありがとう、Josh!)。

また、厳密に言えば、Objective-C の条件は特別なものではなく、C から継承されています。そのため、ブール値として評価する必要がある場合、式は ではなく として扱われBOOLますint

// Does this break when foo is 'dangerous'?`
self.titleLabel.hidden = foo ? YES : NO;

いいえ、そうではありません。(expr)「ブール」式として使用すると、 と同等(expr != 0)です。ここにはリスクはありません。

// I'm pretty sure it breaks now
self.titleLabel.hidden = ((BOOL)foo) ? YES : NO;

iOS では 8 ビットである にBOOL型定義されているだけなので、これは壊れる可能性があります。signed charしたがって、foo(32 ビット) ポインターである が 8 ビットに切り捨てられ、ポインターの下位 8 ビットがすべて 0 であったが、ポインター自体が ではなかった場合nil、これは誤って false を報告します。この余分で、醜く、危険なキャストをしたくありません。より明確にしたい場合は、次のように記述します

var = (obj != nil) ? valueOne : valueTwo;

代わりは。

于 2013-01-25T20:30:09.837 に答える
1

最初の 2 つのサンプルにはキャストがありません。if(expr) を書くことは if(expr == 0) を書くことと同じです。

あなたが参照している記事で説明されているように、3番目の例は実際に壊れる場合があります。

于 2013-01-25T20:31:47.747 に答える