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

OlyaGracheva

macrumors newbie
Original poster
Oct 17, 2008
13
0
Happy New Year everyone!

Hi there! I'm hoping that someone can help me out with the question below. I'm trying to understand pointers in Objective-C and am having a little difficulty in understanding the following. I'll be most grateful if someone can help. Many thanks in advance.

Olya.


From what I understand (and please correct me if I'm wrong):

int x, count = 10;
int *hello;
hello = &count;
x = *hello;

Here the variables x and count are declared to be of type integer. Additionally, the variable count is assigned the value of 10.

hello is a pointer to type integer. hello is then assigned the address of count.
In order to access the value of count, hello must have an asterisk in front of it, ie, *hello.

So, x is assigned the value of whatever is in count and in this case, 10.

However...

Fraction *myFraction = [[Fraction alloc] init];
[myFraction someMethod];

Here, if I understand correctly, myFraction is a pointer to an instance of Fraction class.

myFraction is pointing to (or rather assigned the address of) an object which has been assigned memory and initialised.

Surely, in order to access the object that myFraction points to, I ought to write:

[*myFraction someMethod];

Given the way in which x accessed the value of count, surely in order to access the object, one ought to write this and not:

[myFraction someMethod];

In addition, if I have

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *str = @"Programming can be a headache";
NSLog (@"%@\n", str);

Why is str being treated as an object above? Or is str an object and in which case, why would I want to make it point to an instance of NSString class? Surely, I ought to be able to just assign an object to str?

Thank you again in advance.

Happy New Year.
 
From what I understand (and please correct me if I'm wrong):

int x, count = 10;
int *hello;
hello = &count;
x = *hello;

Here the variables x and count are declared to be of type integer. Additionally, the variable count is assigned the value of 10.

hello is a pointer to type integer. hello is then assigned the address of count.
In order to access the value of count, hello must have an asterisk in front of it, ie, *hello.

So, x is assigned the value of whatever is in count and in this case, 10.

That's all correct. The asterisk is the dereference operator, which takes a pointer and returns the value at the address contained in the pointer.

However...

Fraction *myFraction = [[Fraction alloc] init];
[myFraction someMethod];

Here, if I understand correctly, myFraction is a pointer to an instance of Fraction class.

myFraction is pointing to (or rather assigned the address of) an object which has been assigned memory and initialised.

Right again.

Surely, in order to access the object that myFraction points to, I ought to write:

[*myFraction someMethod];

Given the way in which x accessed the value of count, surely in order to access the object, one ought to write this and not:

[myFraction someMethod];

Nope, this is where Objective-C syntax kicks in, and you're not dealing with C any more. There are no "concrete" object instances in Objective-C. There are only pointers to objects. The message pass syntax in objective-C is an pointer to an object followed by the message to be passed, including parameters.

In addition, if I have

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *str = @"Programming can be a headache";
NSLog (@"%@\n", str);

Why is str being treated as an object above? Or is str an object and in which case, why would I want to make it point to an instance of NSString class? Surely, I ought to be able to just assign an object to str?

@"" syntax is an NSString literal. This kind of expression evaluates to an NSString *. You can assign any NSString pointer to str, but in this case the @"" syntax is being used to generate an NSString rather than one of the NSString factory methods or initWith... initializers.


Hope this helps. Good luck!

-Lee
 
Lee,

Hi there! Thank you very much for your help. I very much appreciate your speedy response.

You've been most helpful.

Thank you.

Olya
 
Fraction *myFraction = [[Fraction alloc] init];
[myFraction someMethod];

Here, if I understand correctly, myFraction is a pointer to an instance of Fraction class.

myFraction is pointing to (or rather assigned the address of) an object which has been assigned memory and initialised.

Surely, in order to access the object that myFraction points to, I ought to write:

[*myFraction someMethod];

Like lee210 said, this is Objective-C syntax. You are quite astute for noticing this, though. In C++, a different object-oriented offspring of C, one would indeed have written

myFraction->someMethod();

using the "arrow operator" to indicate that myFraction is indeed a pointer. It is not that hard to get used to though, because in Objective-C all objects are referenced to through pointers.

Have fun programming!
 
Sander,

Hi there! Thank you for that.

Yes, little details like that annoy me but I'm glad there was a simple answer to the question. It never occurred to me that because Objective-C is OO, that its syntax would differ from C (a language that isn't OO). I guess I just presumed that because Objective-C is an extension of C that its syntax would be similar.

Still, I'm glad I asked.

Happy New Year.

Olya.
 
But where is the object???

Fraction *myFraction = [[Fraction alloc] init];
[myFraction someMethod];


Here, if I understand correctly, myFraction is a pointer to an instance of Fraction class.

As I get that part too.

myFraction is pointing to (or rather assigned the address of) an object which has been assigned memory and initialised.

I get this first part about a pointer being assigend to an object . . . but the question for me is . . . What object? Where is it? I don't see the object getting instantiated. How does the pointer get assigned to said object?



Or is the way it goes . . .


Fraction *myFraction = [[Fraction alloc] init];


Where a Fraction object is allocated memory and initializes, but is not given an actual variable name like most other languages. Its just a Fraction object out in space with a tether to the pointer of myFraction?
 
Fraction *myFraction = [[Fraction alloc] init];


Where a Fraction object is allocated memory and initializes, but is not given an actual variable name like most other languages. Its just a Fraction object out in space with a tether to the pointer of myFraction?

-alloc gets some memory on the heap, init initializes it, = assigns its address to a variable, and Fraction *myFraction declares a pointer named myFraction to be assigned to.

This is similar to Fraction *myFraction = malloc(sizeof(Fraction)); in C.
 
Catfish_Man pretty much covered it, but when you ask "where" a Fraction object is, and stated that it's "not given a variable name". The "where" is on the heap, the area of memory used for dynamically allocated space. Essentially if something is not on the stack (which is used for storing local variables for a particular stack frame, which is generally one per function call), it is on the heap. A few things might be in the program's data area (literals that appear in your code, etc.), but otherwise it's heap or stack.

The statement about not being given a variable name confused me a bit. There are some OO languages that allow local objects that can live on the stack. C++ is an example. You can have a pointer to an object, and use new to allocate space for it on the heap and store the address, also. This is simply not supported by Objective-C. Every object lives on the heap. You could technically alloc an object without storing it's pointer, so there's no "name" associated with that memory. This will likely cause a leak, however. In most cases the "name" for this new object is the variable in which the memory address for the newly allocated object is stored. This is the same when you, for example, malloc memory in C. There is no name for the space allocated, it's just a void * that you can cast to the pointer type you desire, and assign it to a pointer variable.

There are all sorts of different ways languages handle these things. In Java every object lives on the heap, and everything is a pointer. You don't see *s all over, because when you say String, the item on the stack is a pointer to a String, and you assign a pointer to it with a string literal, or you can use new to allocate and initialize a new Object on the heap.

The reason you say that the object is never instantiated (which means generating a concrete copy of an abstract "thing", in this case a class) is likely because the syntax is new to you. Whether an Object in Objective-C is instantiated at the time of allocation or initialization is probably up for debate, but since there are many interfaces that return different types of Objects at initialization time, it's probably easiest to consider initialization the point that the true Object is instantiated.

Hopefully this clarifies things a bit for you. If not, don't hesitate to ask.

-Lee
 
So why are the parens needed in the getters around NSString* below?

--------------------------------------------------------------

#import <Cocoa/Cocoa.h>

@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- (NSString*) caption;
- (NSString*) photographer;

- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;

@end
 
Because that's the Objective-C syntax. If a return value is a primitive, it would still be in parens. If the type of a parameter was a primitive, still in parens. That's the required syntax.

-Lee
 
Code:
- ([COLOR="RoyalBlue"]NSString*[/COLOR]) photographer;

In this case, you are specifying the type of the return value.

Code:
- (void) setPhotographer: ([COLOR="RoyalBlue"]NSString*[/COLOR])input;

In this case, you are specifying the type of parameter that the method expects.

The parens themselves are standard C syntax used in type casting.

Note also the "-" used at the beginning of the method declaration. This is to indicate an "instance method" which will be called in the context of an instantiated object (the object's instance variables will be visible within the method). You will also see methods declared with a "+" instead: these are class methods, in which no instance variables are visible to the method.
 
This is also something I've been struggling with; I have a passing knowledge of C, and I'm currently taking C++ this semester (online), but I'm learning Objective-C for work for some iPhone/iPad development.

So basically, almost everything (definitely all objects) is created as a pointer, and that's that. There's no rhyme or reason, at least none I need to fully understand (although that would be nice), but that's just how it is?

This thread's definitely been very helpful, I guess I just don't quite grasp the concept of a pointer.. I know that it POINTS to an address in memory (hence the *) and that value stored in memory can be retrieved using &, but that's about all I get.

Thanks!
T.J.
 
This thread's definitely been very helpful, I guess I just don't quite grasp the concept of a pointer.. I know that it POINTS to an address in memory (hence the *) and that value stored in memory can be retrieved using &, but that's about all I get.

The reason pointers are so useful is because they're very lightweight and so it allows your program to operate much faster.

To use a metaphor: let's say you were trying to map out the arrangement of cargo containers on a container ship. You could physically move each container around with a crane, but it would be much easier to use a diagram and do your calculations on the representation of the actual containers before using the crane.

Pointers are using the same principle. They are just addresses to the location of the object they represent.
 
Good metaphor. Makes a bit more sense. I didn't really think about the cost of digging into memory, changing an object, and putting it back.. this whole memory management thing is new to me with Objective-C. My programming background is mainly web-based.. and I don't deal with memory in HTML or JavaScript, haha.

Thanks.
 
Hey everyone,

Great thread! I'm still confused by one thing here that I'm just not wrapping my head around.

There are examples in setter or methods that look like (NSString *):

Code:
- (void) setPhotographer: (NSString*)input;

yet inside a method I've seen this syntax

Code:
NSString *str = @"Test";

What does the * mean in the (NSString version)? Is this a pointer to the result of the setter/method or just saying it's expecting a point of type NSString.

Thanks much!
 
Hey everyone,

Great thread! I'm still confused by one thing here that I'm just not wrapping my head around.

There are examples in setter or methods that look like (NSString *):

Code:
- (void) setPhotographer: (NSString*)input;

yet inside a method I've seen this syntax

Code:
NSString *str = @"Test";

What does the * mean in the (NSString version)? Is this a pointer to the result of the setter/method or just saying it's expecting a point of type NSString.

Thanks much!

Its saying the method parameter expects a pointer type of NSString. (Or id or nil, but the compiler will give a warning) The mothod itself returns void (or nothing)



This one:
Code:
NSString *str = @"Test";

That creates a pointer that points to the string literal @"Test" somewhere in the program itself.
 
I actually recommend learning C before you really jump into objective-c. Not only is Objective-C a superset of C(so you will be learning some objective-c along the way), by learning C you will really get a much better idea of what the compiler and your computer are actually doing.

Understanding things like pointers and the cost of memory access etc. are pretty fundamental to writing well-behaved code. I actually recommend people learn C before they learn ANY high level language as it gives you a much better grasp of not only what is going on, but why certain things are the way they are.
 
Sorry for bumping an old thread, but I only have a quick question and this thread is still on the first page anyway. :eek:

Surely, in order to access the object that myFraction points to, I ought to write:

[*myFraction someMethod];

Given the way in which x accessed the value of count, surely in order to access the object, one ought to write this and not:

[myFraction someMethod];


Nope, this is where Objective-C syntax kicks in, and you're not dealing with C any more. There are no "concrete" object instances in Objective-C. There are only pointers to objects. The message pass syntax in objective-C is an pointer to an object followed by the message to be passed, including parameters.

I look at the code, and think that I want to do Object.someMethod(), which in Objective-C is [Object someMethod]. Whenever I see a pointer, I think of it as a memory address, eg 0x01fe9782, which is just an integer.

eg. char *ptr = 'a' // ptr has a value of 0x07dc8314

From now on, using ptr would give you the memory address, and using *ptr would give you the object at that memory address, in this case, 'a'.

So when I see:
Object *myObject = [[Object alloc]init];
then:
[myObject someMethod];
I see it like this:
[0x01fe9782 someMethod];
Which just doesn't make sense. How can the number of a memory address have a method?

I know this is wrong, but the following would make more sense to me:
[myObject* someMethod];
(Dereferencing to find the object at that memory address and then performing the method on the object.)

Can anyone explain why this is? I can't get around the fact that it reads as if you are operating on the pointer and not on the object.
 
So when I see:
Object *myObject = [[Object alloc]init];
then:
[myObject someMethod];
I see it like this:
[0x01fe9782 someMethod];
Which just doesn't make sense. How can the number of a memory address have a method?
You're too wrapped up in the low-level mechanics. The number of a memory address doesn't have a type, either, yet dereferencing a pointer to a char has a completely different result than dereferencing a pointer to a double. For example:
Code:
int n = *aptr;
produces very different code (and results) depending on whether aptr is declared as pointer to char or pointer to double. Worse, you can reinterpret one type as another, even if aptr is declared as pointer to void:
Code:
int n1 = *((char*)aptr);
int n2 = *((double*)aptr);
How is all that possible with the same "number of a memory address"? The answer lies in the interpretation of the memory address at a higher level of abstraction than simply a memory address number. Abstraction is at the heart of all computer programming.

I know this is wrong, but the following would make more sense to me:
[myObject* someMethod];
(Dereferencing to find the object at that memory address and then performing the method on the object.)

Can anyone explain why this is? I can't get around the fact that it reads as if you are operating on the pointer and not on the object.
You are operating on the pointer. It comes down to what operation you're performing on the pointer.

Sending a message to an object is compiled into a call to the C function objc_msgSend(). That function takes a pointer to an object, not an object parameter. That is, it takes a reference to an object struct, not a private copy of an object struct.

The reasons for this should be obvious if you break it down. In order to operate on a thing pointed at, you either need a pointer to the thing (call by reference), or you need a private copy of the thing (call by value). Alterations to private copies have no effect on the original thing pointed at, so if one potential goal is to alter the original thing pointed at, there's only one option left: call by reference.

It's also the same reason that C arrays are passed by reference, not by copy. Even in languages like Java, all arrays and objects are passed by reference, not by copy. Only primitives are passed by copy (i.e. by value).

http://developer.apple.com/library/...rence/ObjCRuntimeRef/Reference/reference.html

http://developer.apple.com/library/...timeGuide/Articles/ocrtHowMessagingWorks.html
 
Thanks chown33. I skimmed over your answer before and just got back to it to read properly. Noticed you had added even more! :)

How is all that possible with the same "number of a memory address"? The answer lies in the interpretation of the memory address at a higher level of abstraction than simply a memory address number. Abstraction is at the heart of all computer programming.

Yep, I already understood that much. For example, if you pull 10101000 from a location, it means very different things if interpreted as unsigned/signed ints or even a char.

You are operating on the pointer. It comes down to what operation you're performing on the pointer.
<snip>

Ahh. I think I get it now. It just so happens that all methods of a class are defined to operate by pointer. You pass a reference, the method goes to that address and gets/sets things as needed.

As you said, I was thinking of it in the same way as low-level mechanics, where you need to tell it you want to operate on the thing at the memory address, and not the address itself. Evidently, this happens by default with objects as everything is expecting the memory address to begin with!

It does make sense. I spose hadn't really thought about it before. My other OOP experience is in Python, where almost everything is hidden from you, and Java, which conceals the fact you are using pointers in objects (eg. String str = new String, not String *str = new String).
 
I have also had a lot of trouble with the above concepts. The friendly people in this forum really helped me understand it.

So, may I offer these insights which took me a long time to get (because nobody has explained it to me like I am about to, to you) but this is how I understand it in my own way:

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.

You continue to use * for C syntax, which most of the fundamental operations are, within Objective-C code. So *myVar is still a pointer holding address &myVar.

Regarding (NSString*) myString:

The way I look at it is, NSString* is the type. That means, it's a pointer to an NSString. So NSString* is different from NSString and different from int.

So it's not actually NSString with a trailing *. It's NSString* entirely, as a data type (which in this case is a pointer to an NSString, or an NSString pointer).

Perhaps the experts here can verify my understanding of the above.
 
That distinction is exactly why I prefer to write
Code:
NSString* foo;
instead of
Code:
NSString *foo;

Sadly, C breaks this a bit in one small place. To declare more than one NSString you would need
Code:
NSString *foo, *bar;
I consider this to be a minor design bug in C that makes it harder to think about the correct type of things.

Also, I like CFString's way of handling it, which is to use a typedef to make CFStringRef.
 
Sadly, C breaks this a bit in one small place.

It's always funny to me that NSString* foo is the same as NSString *foo.

Does anyone know if this is due to the usual whitespace being ignored, or is it two separate validities for the syntax?

It would confuse me less if it was the latter, actually. (Although I'm not confused now, but had been for a very long time).

Anyway even though I am clear on this point now, I think I will start to just adopt Catfish Man's habit as the best practice, going forward, maybe even go as far as separate lines for the multiple pointer declarations.
 
It's always funny to me that NSString* foo is the same as NSString *foo.

Does anyone know if this is due to the usual whitespace being ignored, or is it two separate validities for the syntax?

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
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.