PDA

View Full Version : the * in objective-C




ketels
Oct 16, 2010, 05:01 AM
I'm trying to learn Objective-C, but there is one thing I do not really get a grip on.
I understand that if one writes:
NSString *name;
it is a pointer to NSString object.

But why do you write the star inside the brackets when you write:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

Why not write:
- (UITableViewCell)*tableView



crackpip
Oct 16, 2010, 08:01 AM
I'm trying to learn Objective-C, but there is one thing I do not really get a grip on.
I understand that if one writes:
NSString *name;
it is a pointer to NSString object.

But why do you write the star inside the brackets when you write:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

Why not write:
- (UITableViewCell)*tableView

The bit inside the parentheses indicates the datatype of the arguments or the function result. In Obj-C you don't pass/return objects directly, you pass/return pointers to objects. So (UITableViewCell *) means the function will return a pointer to a UITableViewCell object.

crackpip

ketels
Oct 16, 2010, 10:48 AM
The bit inside the parentheses indicates the datatype of the arguments or the function result. In Obj-C you don't pass/return objects directly, you pass/return pointers to objects. So (UITableViewCell *) means the function will return a pointer to a UITableViewCell object.

crackpip

I think I almost get it...
But I still don't understand why you don't write (UITableViewCell)*tableView since you write NSString *name;

(marc)
Oct 16, 2010, 10:56 AM
I think I almost get it...
But I still don't understand why you don't write (UITableViewCell)*tableView since you write NSString *name;

The return type is always written inside of the parentheses. There's nothing to really "understand" here, it's syntax.

Sydde
Oct 16, 2010, 11:37 AM
The syntax is basically a typecast. For example, if you were to declare
int *someInt;
float *someNum;
and for some reason needed to assign one pointer to the other, you would use similar syntax
someInt = (int *)someNum;
to cast the type. This is for tranferring a pointer. If you wanted the referenced value, "aFloatingPointNum = (float)*someInt;" is the syntax you would use.

amorya
Oct 16, 2010, 01:49 PM
I think I almost get it...
But I still don't understand why you don't write (UITableViewCell)*tableView since you write NSString *name;

It's the same thing to write

NSString *name

as it is to write

NSString* name

chown33
Oct 16, 2010, 01:55 PM
Also see this recent thread, starting at post #24:
http://forums.macrumors.com/showthread.php?t=625899

Stratoukos
Oct 18, 2010, 10:28 AM
As amorya said, I think you are confused by the syntax.

In Objective-C, as in most languages that have pointers, a pointer to something is a distinct type from a pointer to something else. So a pointer to int is neither a pointer to something that happens to be an int nor an int that happens to be pointed at. It's a type of its own.

When declaring a variable, the syntax is:
type name
So, when the variable is a pointer to NSString, the syntax is:
NSString *name
The fact that there isn't any space between * and the name is confusing. The * logically belongs to the type.

When declaring a method, the syntax is:
-(returnType)methodName:(parameterType)variableName;
So, when, for example, the method takes a pointer to NSString and returns a pointer to UITableViewCell, the syntax is:
-(UITableViewCell *)methodName:(NSString *)variableName;

Just remember that the fact that a variable is a pointer is about its type, not its name.

jared_kipe
Oct 18, 2010, 12:21 PM
And then there is "id"...

HiRez
Oct 18, 2010, 02:49 PM
You're right to be confused, because it is confusing. The * symbol probably causes more confusion in C than anything else, and it's one of the reasons that other derived languages such as Java have tried to eliminate it. Inconsistencies like Apple's "id" addition don't help.

vocaro
Oct 18, 2010, 03:15 PM
The syntax is basically a typecast.

No! The "(UITableViewCell *)" in ketels's snippet is simply a declaration of the method's return type. This is definitely not an example of typecasting.

The * logically belongs to the type.

Yes, precisely. This is not so much a syntax issue as a whitespace issue. Instead of:

NSString *name;

it would actually be more correct to write:

NSString* name;

to more clearly indicate that the asterisk is part of the variable's type, not its name. Some programmers do use the latter convention for this very reason, but somehow the former has taken hold, illogical as it is.

GorillaPaws
Oct 18, 2010, 03:23 PM
Some programmers do use the latter convention for this very reason, but somehow the former has taken hold, illogical as it is.

I can remember being very confused by this when I was first learning (especially because it was inconsistent from programmer to programmer). I think this is one of those issues where freedom of whitespace makes things less clear.

chown33
Oct 18, 2010, 05:23 PM
Some programmers do use the latter convention for this very reason, but somehow the former has taken hold, illogical as it is.

It's logical when you consider this won't work:
NSString* name, city;

Then it becomes clear that * is a modifier that must appear for every declared pointer variable.

HiRez
Oct 18, 2010, 05:59 PM
It's logical when you consider this won't work:
NSString* name, city;

Then it becomes clear that * is a modifier that must appear for every declared pointer variable.

Yep, that's the problem. However, I always declare only one variable per line no matter what. Then, not a problem.

NSString* name;
NSString* city;

I find the one declaration per line rule also helps when adding or deleting variables, and adding comments (you can easily add // after the variable without having to break it out into its own line)

jared_kipe
Oct 18, 2010, 06:32 PM
I agree with both of you. I personally prefer to write NSObject *object; as its what you see in the documentation and sample code.

However I almost ALWAYS will declare objects one per line. And usually primatives all at once. As long as they are somewhat related.
E.G.

int counter, errorCount;
double stdDev, mean, range;

NSArray *inputArray;
NSArray *outputArray;

// actual code for method blah blah

lee1210
Oct 18, 2010, 07:18 PM
However I almost ALWAYS will declare objects one per line. And usually primatives all at once.


What about pointers to primitives or structs? That seems like the more ambiguous case, since missing a * on an Object will be a compile-time error for sure, while missing one on a primitive pointer might just lead to warnings and erroneous run-time behavior.

-Lee

Matthew Yohe
Oct 18, 2010, 07:25 PM
I find the one declaration per line rule also helps when adding or deleting variables, and adding comments (you can easily add // after the variable without having to break it out into its own line)

You can always do this too:
NSString *thing1, *thing2;

HiRez
Oct 18, 2010, 08:07 PM
You can always do this too:
NSString *thing1, *thing2;

For sure, but the point was to keep the * next to the type so it reads more obviously as "string pointer" (or whatever). I think logically that makes more sense, but it's become somewhat standard to do it the "less logical" way. People like to save lines, but Objective-C is such a verbose language anyway, I think it makes sense to strive for more clarity and less compactness where possible. Just my opinion, I know a lot of old school C coders still see the beauty in a bit of code that's as terse and compact as possible.

chown33
Oct 18, 2010, 08:41 PM
... I know a lot of old school C coders still see the beauty in a bit of code that's as terse and compact as possible.

Until they have to perform maintenance on that code. Then they curse the idiot who made it that way. Even when (or especially when) that idiot is the younger version of themselves.

You laugh and shake your head, but you know it's true, because you've seen someone else do it, or done it yourself.

jared_kipe
Oct 18, 2010, 09:08 PM
What about pointers to primitives or structs? That seems like the more ambiguous case, since missing a * on an Object will be a compile-time error for sure, while missing one on a primitive pointer might just lead to warnings and erroneous run-time behavior.

-Lee

Can't remember the last time I needed to declare more than one pointer to a struct or primitive. So it would probably depend on my mood if the time arose.

Sydde
Oct 18, 2010, 10:16 PM
As I recall, I have seen compiler error messages that refer to the indirection symbols "*" and "&" as unaries. Like "+" or "-" before a numeric value, the pointer unaries are modifiers applied to the variable that follows.

For example, you could declare a pointer variable with no whitespace at all
NSString*aString;
or with whitespace on both sides of the "*". I think the proper description of declaration syntax is
type location name;
where location is zero or more "*" indirection unaries. If you tie the unary to the type, you might end up with confusion or mental discomfort when you have to deal with double indirection.

No! The "(UITableViewCell *)" in ketels's snippet is simply a declaration of the method's return type. This is definitely not an example of typecasting.
Sorry, I did not mean to say that it was a typecast, just that that is how the syntax makes sense as an extension C grammar.

jared_kipe
Oct 18, 2010, 10:29 PM
Sorry, I did not mean to say that it was a typecast, just that that is how the syntax makes sense as an extension C grammar.

Not really, that part of C grammar is for return type. In objective-C the return type is in () but in C it is not.

int add( int a, int b) {
return a+b;
}
vs
+ (int)addInt: (int) a toInt: (int) b {
return a+b;
}

Mac_Max
Oct 19, 2010, 01:07 PM
Until they have to perform maintenance on that code. Then they curse the idiot who made it that way. Even when (or especially when) that idiot is the younger version of themselves.

You laugh and shake your head, but you know it's true, because you've seen someone else do it, or done it yourself.

Good code comments and documentation goes a long way. I tend to over comment/over document since the penalty for that is a lot less than not knowing what you're looking at.

GorillaPaws
Oct 19, 2010, 07:59 PM
Good code comments and documentation goes a long way. I tend to over comment/over document since the penalty for that is a lot less than not knowing what you're looking at.

That was the approach I started out with. I recently read Clean Code (http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882) and my views on comments have shifted since then. Basically, the authors recommend breaking out chunks of code that you would typically explain with comments, and creating a well-named private methods as a more elegant replacement.

I've also heard that comments should focus on WHY you are doing something, and not a description of WHAT the code is doing. If you have to explain what your code is doing with comments then your code isn't very clearly written. It's my new coding philosophy for now, and I don't pretend to have nearly the knowledge and experience as many of you guys, but I really like the approach they take in "Clean Code" (except for the test driven development stuff--I'm not ready for that just yet).