7

Here is an embarrassingly simple question that I have not been able to find an answer to as I delve into Objective C:

Is there a meaning ascribed to where you put the pointer indicator '*' when declaring or assiging a variable?

I have seen variables defined in different ways:

 NSString  *BLANK_SPACE = @" ";
 NSString const *BLANK_SPACE = @" ";
 NSString * const BLANK_SPACE = @" "; 

Now I know the meaning of the CONST modifier, but I put it there only because when I see the asterisk separated by a space, it is usually before a CONST modifier.

Can someone explain the rationale about where to put the * when declaring/assigning a variable? What is the difference?

Gavin Miller
  • 43,168
  • 21
  • 122
  • 188
JohnRock
  • 6,795
  • 15
  • 52
  • 61
  • Dont know the answer but it's a very good question :). If newton had thought asking question suach as why apple fall? We would be unaware of gravity ;) – TeaCupApp Aug 29 '11 at 00:42
  • Good question. I think the 'C' parts of obj-c are the hardest part for beginners. – kubi Aug 29 '11 at 00:44
  • I'll note that, for a standard pointer declaration such as `NSString * myString;` all of the blanks are optional -- could be `NSString *myString;`, `NSString* myString;`, or `NSString*myString;`. Probably `NSString *myString;` is the most common (and what xCode tends to auto-generate), but I personally prefer `NSString* myString;`, since I associate the "pointerness" of the declaration with the type, not the variable. However, one does need to be careful when declaring multiple variables together (`NSString* myString1, * myString2;`), or, better, avoid multiple declarations on the same line. – Hot Licks Aug 29 '11 at 02:29
  • 1
    Re `const`, the style I see most often (and the one I prefer) is to place it to the left of the type (first thing on the line) when declaring a pointer to a constant value (which is the most common use of `const` ). This is hard to confuse. Then, if the `const` appears anywhere else that's a signals to say to yourself "Whoa! Think about this." – Hot Licks Aug 29 '11 at 02:40
  • @Daniel - If I am not mistaken, wouldn't putting the CONST first, to the left of the type, be declaring a const string as opposed to a const pointer? based on the comments below, I would think that is not what you really want most of the time in objective-c. – JohnRock Aug 30 '11 at 02:25
  • Yes, const to the left makes whatever's pointed to const. But this is the most common use -- `const char*` and the like. `const` has very little use in Objective C, outside of "C-isms" such as `const char*`. – Hot Licks Aug 30 '11 at 03:21

3 Answers3

9

const is a postfix operator that refers to the thing to its left, as opposed to the right. If the const comes first then it applies to the first thing after it. const NSString *foo (as well as NSString const *foo) means that it's a non-const pointer to a const NSString - the pointer value can be reassigned, but the data being pointed to is immutable. NSString * const foo means that it's a const pointer to a non-const NSString - the data being pointed to can change but the location the pointer refers to cannot.

Spacing between the * and other parts of the line are just a matter of style and clarity.

fluffy
  • 5,212
  • 2
  • 37
  • 67
  • 2
    Please also refer to @Caleb's answer about stylistically which placement of the * is more appropriate. This is really rooted in C and some of the ambiguity in that language, but the style prescribed by Caleb really makes it clear what the * applies to. I went through this song and dance with C/C++ many years ago, and while it doesn't make a shred of difference linguistically, it makes a world of difference when you're looking back through old and forgotten code! – SplinterReality Aug 29 '11 at 01:09
  • Here is another thread that also talks about the confusing distinction between const pointers or const objects: http://stackoverflow.com/questions/593498/problem-with-declare-a-global-variable-in-objective-c – JohnRock Aug 29 '11 at 01:26
  • While @Caleb's answer is correct, it doesn't answer the question. The placement of `const` does indeed make a difference. It determines whether the data is constant or whether the pointer itself is constant. – Alexsander Akers Aug 29 '11 at 01:28
2

The trick is to read the declarations from right to left. So:

NSString  *BLANK_SPACE 

Right to left... BLANK_SPACE is a pointer to an NSString.

NSString const *BLANK_SPACE

Right to left... BLANK_SPACE is a pointer to a const NSString.

NSString * const BLANK_SPACE

Right to left... BLANK_SPACE is a const pointer to an NSString.

Finally,

NSString const * const BLANK_SPACE

Right to left... BLANK_SPACE is a const pointer to a const NSString.

Graham Perks
  • 23,007
  • 8
  • 61
  • 83
  • THanks - this is a great explanation. I see now that what adds to the confusion for me is this concept: NSString const *BLANK_SPACE. What does a constant string mean? The link I posted above (http://stackoverflow.com/questions/593498/problem-with-declare-a-global-variable-in-objective-c/3812205#3812205) suggests this is meaningless. Is there a reason to make a constant string? – JohnRock Aug 29 '11 at 02:15
  • In Obj-C its fair to say that the NSString const* syntax makes little sense, since NSStrings are immutable and hence already const. That syntax makes sense for non Obj-C class types (e.g. int, char), and also makes sense in C++ where the notion of const methods exists. There, only const methods can be called on const objects. Obj-C has nothing like that; it relies on the simpler idea of objects that can't be changed (like NSString)! – Graham Perks Aug 29 '11 at 13:38
1

The position of the * relative to the variable name doesn't matter to the compiler. Some prefer to put the * with the variable, though, because it avoids possible confusion when declaring multiple variables:

char* a, b;  // a is char* and b is char, but both look like char*
char *a, b;  // looks a little more like the truth: a is char*, b is char

However you always refer to objects in Objective-C via pointers, so you'd never do something like the first line below:

NSString *a, b;  // WRONG: a is a pointer to an NSString object, b is just wrong.
NSString *a, *b; // OK: both a and b are pointers to NSString objects

The position of const, on the other hand, does make a difference:

int * const a; // a points to an int, and a can't be modified to point to some other int
int const * a; // a points to an int, and that int can't be changed

Now, const doesn't make a lot of sense with respect to objects. For one thing, NSString represents an immutable string, so declaring one const doesn't add much. For another, one generally modifies an object in Objective-C by sending a message, not by changing the object's ivars directly, and I don't believe the compiler will prevent changes made via messages. Therefore, a const pointer makes sense, a pointer to a const object, not so much:

NSString * const BLANK_SPACE = @" "; // makes sense; pointer BLANK_SPACE can't change
NSString const * BLANK_SPACE = @" "; // not useful
Caleb
  • 124,013
  • 19
  • 183
  • 272
  • 2
    `NSString const *` and `NSString * const` are not the same thing. – lemnar Aug 29 '11 at 00:56
  • @lemnar, you're right of course -- I was thinking about the position of the * relative to the variable name and not the const. – Caleb Aug 29 '11 at 01:26
  • @Caleb, my apologies for, in my confusion, inadvertently asking two questions at once. – JohnRock Aug 29 '11 at 01:45
  • @JohnRock, no worries -- I've updated my answer to be more complete, and a couple of downvotes are no big deal. – Caleb Aug 29 '11 at 01:49