Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

zippyfly

macrumors regular
Mar 22, 2008
141
0
It's insignificant whitespace being ignored.

These all have the same meaning:
Code:
NSString* foo;  // post-star space

NSString *foo;  // pre-star space

NSString*foo;  // spaceless

NSString
*
foo;  // newlined

NSString /* commented */
* // newlined
foo  /* and accepted */
;  // this too

The only time whitespace is significant is when it separates tokens that would otherwise be parsed as a single token. Since punctuation other than '_' is invalid in a C name, operators serve as delimiters between tokens. This can lead to some odd expressions:
Code:
foo = bar---quux;
can be parsed as either of these:
Code:
foo = bar-- - quux;
foo = bar - --quux;
The correct one is the former.

There is ample reason for the Obfuscated C Contest.
http://en.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest

Wow, extremely eye-opening and instructive. Thanks!
 

ianray

macrumors 6502
Jun 22, 2010
452
0
@
It's always funny to me that NSString* foo is the same as NSString *foo.

I wonder if it helps to know that C variable declarations must be read backwards? Thus, the above example is:

  • foo is
  • a pointer to
  • NSString

The '*' is simply an operator, and its placement (closer to type, or closer to identifier) is a stylistic matter. Hope that helps :)
 

Catfish_Man

macrumors 68030
Sep 13, 2001
2,579
2
Portland, OR
I wonder if it helps to know that C variable declarations must be read backwards? Thus, the above example is:

  • foo is
  • a pointer to
  • NSString

The '*' is simply an operator, and its placement (closer to type, or closer to identifier) is a stylistic matter. Hope that helps :)

It's true, and for complex types that's definitely the way to read them, but I'm not sure if that's a useful way to think about it. I think "(foo) is a (pointer to NSString)" is more likely to lead to correct reasoning than "(foo) is a (pointer) to (NSString)".

"foo is an (NSString reference)" is probably the safest way to think about it, since you don't actually want to use any of the pointer operators (*, ->, postfix []) on an ObjC object reference.
 

firewood

macrumors G3
Jul 29, 2003
8,106
1,343
Silicon Valley
...I think "(foo) is a (pointer to NSString)" is more likely to lead to correct reasoning than "(foo) is a (pointer) to (NSString)".

"foo is an (NSString reference)" is probably the safest way to think about it, since you don't actually want to use any of the pointer operators (*, ->, postfix []) on an ObjC object reference.

But you can use the pointer operators -> and [] on object references. If your code is mix of C and Objective C (for code portability or performance reasons) this is actually useful for passing stuff between the two language environments without performance/size hits.

And the term "correct reasoning" sounds too Orwellian to me. I prefer teaching the all the politically incorrect coding paradigms and their corresponding weaknesses and strengths.
 

Sydde

macrumors 68030
Aug 17, 2009
2,552
7,050
IOKWARDI
But you can use the pointer operators -> and [] on object references. If your code is mix of C and Objective C (for code portability or performance reasons) this is actually useful for passing stuff between the two language environments without performance/size hits.

I am missing something here. Objective-C is a different language environment from C? AFAICT, objective-C is merely C with a few small extensions, why would you need to "pass stuff between" two environments that are not separate things?

As for performance and portability, what you say looks entirely backwards to me. Directly accessing "opaque" structures like NSObject is a recipe for breaking portability up or down the road, and if you get an observable performance advantage from bypassing the normal mechanisms, I would guess that your code has some serious design flaws.
 

Catfish_Man

macrumors 68030
Sep 13, 2001
2,579
2
Portland, OR
But you can use the pointer operators -> and [] on object references. If your code is mix of C and Objective C (for code portability or performance reasons) this is actually useful for passing stuff between the two language environments without performance/size hits.

And the term "correct reasoning" sounds too Orwellian to me. I prefer teaching the all the politically incorrect coding paradigms and their corresponding weaknesses and strengths.

Correct in the sense of "doesn't contain bugs", and "behaves as expected", not in the sense of "approved". Reasoning about things correctly is the foundation of all programming and math (practically the definition of math, really).

For example: in the modern (x86-64 only) ObjC runtime, what do you think -> actually does on an ObjC object? It's not the same as what it does on a C struct or C++ object, although it does enough trickery that it appears to be the same except for being a bit slower.
 

firewood

macrumors G3
Jul 29, 2003
8,106
1,343
Silicon Valley
As for performance and portability, what you say looks entirely backwards to me. Directly accessing "opaque" structures like NSObject is a recipe for breaking portability up or down the road, and if you get an observable performance advantage from bypassing the normal mechanisms, I would guess that your code has some serious design flaws.

Backwards is important. I have portable (and profitable) C code that runs on embedded systems with only a few 10's of kB of available memory. I can also easily interface this same portable C code directly into Cocoa Touch objects for an attractive UI on the iPhone.

Up the the road I don't care as much, as on a rack of Xserves I could use alternate available "portable" code libraries that couldn't possibly survive as long on anything with a tiny battery. Let's all increase our carbon footprint on the planet by encouraging silly code portability requirements without knowing the trade-offs.
 

Mr Skills

macrumors 6502a
Nov 21, 2005
803
1
When you use the brackets [ ] then you do not need to dereference with the * operator. Like others have said, the * is for C syntax. You can almost always assume that the first item after the opening [ is an object and you can just treat that [ to have a built-in dereferencing operation. The second item preceding the closing ] would be the message to send to that object.

So is one simplistic way of thinking about it that "[ comes with invisible built-in *"?
That sort of makes sense in my head... :)
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
So is one simplistic way of thinking about it that "[ comes with invisible built-in *"?
That sort of makes sense in my head... :)

Whatever floats your boat. There are some operators that work on pointers, like -> on a pointer to a struct, or * to dereference a pointer. [] as a message pass acts on a pointer. I wouldn't think of an "implicit *" or something, because you NEVER dereference a pointer to an Object in Objective-C. You don't. That's just how the object system works.

-Lee
 

Sydde

macrumors 68030
Aug 17, 2009
2,552
7,050
IOKWARDI
This is probably more information than anyone really needs or wants, but to be totally pedantic, square brackets could be thought of as a sort of macro: the objective-c syntax
Code:
[anObject setAProperty:aValue];
would translate to a function call that would look something like
Code:
setAPropertyIMP( anObject, setAPropertySEL, aValue );
The "setAPropertyIMP" is a function located via a pointer derived from @selector( setAProperty ), which returns the value setAPropertySEL (why they include the selector in the function call is not entirely clear to me, but there must be a good reason). Therefore, when you define a method using
Code:
- (void)setAProperty:(int)aValue;
its C prototype effectively looks like
Code:
void setAPropertyIMP( id self, SEL theMethod, int aValue );

Theoretically, each method call would involve looking up a function pointer (of type "IMP") using the method selector (an integer of type "SEL") and calling the function. In reality, most or all method IMPs are resolved and cached at launch time or shortly thereafter so that the actual method call takes almost no overhead.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
This is probably more information than anyone really needs or wants, but to be totally pedantic, square brackets could be thought of as a sort of macro: the objective-c syntax
Code:
[anObject setAProperty:aValue];
would translate to a function call that would look something like
Code:
setAPropertyIMP( anObject, setAPropertySEL, aValue );
The "setAPropertyIMP" is a function located via a pointer derived from @selector( setAProperty ), which returns the value setAPropertySEL (why they include the selector in the function call is not entirely clear to me, but there must be a good reason). Therefore, when you define a method using
Code:
- (void)setAProperty:(int)aValue;
its C prototype effectively looks like
Code:
void setAPropertyIMP( id self, SEL theMethod, int aValue );

Theoretically, each method call would involve looking up a function pointer (of type "IMP") using the method selector (an integer of type "SEL") and calling the function. In reality, most or all method IMPs are resolved and cached at launch time or shortly thereafter so that the actual method call takes almost no overhead.

Why make that all up when you could just refer to obj_msgsend?

It returns id, not void, but otherwise your version is close.

-Lee
 

firewood

macrumors G3
Jul 29, 2003
8,106
1,343
Silicon Valley
Objective C is fairly efficient memory-wise. It's far more efficient to use a pointer to an object, rather than to copy around an entire arbitrary object, just to tell the runtime where and how to send a message.

So NSBigObject *foo; only reserves valuable memory space for a 4 (maybe 8) byte pointer, instead of a honkin bigabyte.

And, after the bigabyte is alloc'd, [ foo bar ]; only needs to send the runtime a few bytes of pointer so that the runtime knows where to look up where to send the message, the whole bigabyte object doesn't need to be copied or allocated again or on the stack.

Un-thinking programmers wasting memory and processor cycles is one reason why computers and data centers are contributing so much to global carbon.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.