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

Miglu

macrumors member
Original poster
Jan 22, 2010
74
0
I have learned Java and am having a problem with pointers in Objective-C. This is from my Java book's "The allocation of memory to variables" section:

"The local variable used to store the object appears on the stack just as if it were a local variable holding a primitive type. That particular variable, however, holds only the memory address of the object, which is stored in the heap."

This is from the "Passing arrays as parameters" section:

"If you pass a primitive value like an integer, Java copies the value, which means that it is impossible for a method to change it. ... however, passing an object as parameter to a method means that only the reference is copied, so the method effectively shares the object with the caller."

Are the facts in these two quotes always true in Objective-C? The Java book does not even mention pointers, and I am wondering why they are needed so much in Objective-C. Is the definition of variable different in the two languages?
 
Objective-C is lower level than Java. In reality EVERY non-primative variable in Java is a pointer. Think about the dreaded "NullPointerException" you can get in Java...
 
The way objects are handled in both Java and Objective-C are more similar than initial appearances portray. In Java, you only have one way to refer to an Object. You can't actively manipulate the pointer to the Object, but a pointer is all you have. Things like the dot operator to access an object's ivars or methods know this and always do what you want to the Object on the other side of the pointer. You can't retrieve the address yourself and manipulate it, and you can't "dereference" the pointer, all of this is handled behind the scenes for you. You can never have a "concrete" Object on the stack, pass it around, etc... you only deal with the reference/address of the Object.

Essentially these same rules apply to an Object in Objective-C, except that the pointer is always explicit instead of Java where the pointer is always implicit. The only real difference is you can add levels of indirection in Objective-C. That's to say, you can have a pointer to an NSObject *. You can never have a concrete Object on the stack in Objective-C. The only thing you can do to an Object pointer is pass messages to it (please ignore accessors invoked via the ".". They do nothing but muck with and confuse the syntax. They are a shortcut for a message pass. A message pass is ALL you do to an Object pointer).

You can contrast this with the system in C++ where you can have concrete Objects on the stack, and pointers to Objects. You need to use different operators based on what you're dealing with, either -> to act on an Object pointer or . to act on a concrete, "local" Object. This distinction does not exist in Objective-C or Java, everything is via a pointer in both. The only difference is in Objective-C the pointer syntax used for pointers to other primitive types is extended to Objects instead of obscuring the fact that you're dealing with a pointer like Java.

Hope this is helpful, i know it sounds sort of obtuse, but it's really not so bad once you get a little more cozy with Objective-C, and especially if you spend a little time learning about pointers and how they are used in plain C. Once you do, hopefully it will make more sense that you never have an NSObject, only an NSObject *, and you'll never dereference an NSObject * with &.

-Lee
 
My question is, when you use dot syntax in Cocoa via @property / @synthesize , does it always generate a method? It seems to me that the optimizer would look at "[self getIVar]" generated from self.iVar and say, "well, that is a silly waste of a method call when it can just be converted directly to an offset".
 
Thanks. Now I understand. A book called "Learn Objective-C on the Mac", as well as the previous book in the series, "Learn C on the Mac", does not explain this. Neither does the "C Programming" Wikibook. It should be edited to have a chapter about coming from different languages and this should be explained in the Java section. However, is the definition of variable the same for the languages? It seems that a pointer is called a variable in Java.
 
My question is, when you use dot syntax in Cocoa via @property / @synthesize , does it always generate a method? It seems to me that the optimizer would look at "[self getIVar]" generated from self.iVar and say, "well, that is a silly waste of a method call when it can just be converted directly to an offset".

From:
http://developer.apple.com/mac/libr...html#//apple_ref/doc/uid/TP30001163-CH11-SW17

The dot syntax is purely “syntactic sugar”—it is transformed by the compiler into invocation of accessor methods (so you are not actually accessing an instance variable directly).

What this means is that you get to keep all of the power of a message pass when using the ".", an ivar is never accessed directly. So message forwarding, dynamic-woozamawhatzits, etc. will still work fine when using the ".".

<snip>However, is the definition of variable the same for the languages? It seems that a pointer is called a variable in Java.

A variable is a place to hold a value. In strongly-typed languages, every variable has an associated type. In OOP languages, i like to think of Objects as a wholly different sort of thing than a variable, because they don't just hold a value, but a whole bunch of values, and methods that go with them. I think of a variable as holding a primitive type. In a language like C/Objective-C, one primitive type is a pointer. The value stored is a memory address, and when you go there you find the type that is being pointed to. Sometimes that's another primitive like an int, sometimes in Objective-C it is an Object. There are no user-facing pointers in Java at all, period. When you say:
Code:
java.lang.String myString = null;
in Java, this is a pointer to a String, but you don't really have to deal with that. It's null right now, if you assign something to it it will point to that thing. But you don't really think about reaching out into memory to grab that Object, etc. you just say:
Code:
java.lang.String myString = "xyz";
int x = myString.length();
Sure, it's going to dip it's finger somewhere into the aether (you don't get to know where, without some JVM tomfoolery) and calls length on the myString object. You don't have to worry about the specifics of where that thing is, etc.

It doesn't hurt to KNOW that those are pointers in Java, you just don't really have to worry about it. Things like assigning one Object to another do make this more clear, though. No copy is made, etc... just the pointer is assigned, so now two things are looking at the same piece of memory. In the case of Strings in Java, this doesn't much matter because they are immutable, but if you had a mutable thing, and assigned one Object to another, changing the Object via one of those references is going to result in a change when you look at it with the other, because they are both pointing to the same thing.

-Lee
 
Is there any advantage at all of using self.iVar versus directly accessing iVar? I have seen code written this way and it perplexes me that anyone would want to do that.
 
The simplest way to remember whether or not a value is a pointer: size.

Variables' values have to live somewhere, whether on the stack, as instance variable within an object, or in allocated memory. A number, like an int or a float, is always a specific known size at compile time. structs are also defined at a fixed size. These things may exist in a specific location because the compiler knows how much space to reserve for them.

Conversely, an object instance, such as a string, is not a known size prior to runtime. If your code cannot know the size of a value, you can pretty well assume that the name you use to access that variable will be a pointer.
 
Is there any advantage at all of using self.iVar versus directly accessing iVar? I have seen code written this way and it perplexes me that anyone would want to do that.

Methods can be overridden. Direct access to ivars cannot.

Sometimes it's better to maintain flexibility (properties and dot-accessors) as long as possible during dev, especially if the performance effects are insignificant.

Properties don't require one-to-one correspondence to ivars. Simple example: the mean or median value of an array-like class can be a property, despite not having an ivar.

Properties can also be KVO'ed and KVC'ed.
 
Properties don't require one-to-one correspondence to ivars. Simple example: the mean or median value of an array-like class can be a property, despite not having an ivar.

Properties can also be KVO'ed and KVC'ed.

A simpler and more relevant example might the an array's object count. A table datasource would want to observe its source array's count and reload the table when ever that value changes.
 
Is there any advantage at all of using self.iVar versus directly accessing iVar? I have seen code written this way and it perplexes me that anyone would want to do that.

self.iVar is really only used for objects (non-primative) data types. The reason is that you can use the built in memory management.

EXAMPLE:
@property (retain) NSString *myString;

lets say we want to put a string there.
if we do;
myString = [NSString stringWithFormat: @"%@", someOtherString];

Then after our next run loop myString is not valid anymore. Why? because the method stringWithFormat: returns an autoreleased string.
self.myString = [NSString stringWithFormat: @"%@", someOtherString];

works perfectly.

AND!!!!
if myString was already assigned to a string variable that was retained, version1 leaks that first string, version two does not!

The method generated for setMyString would look something like this.
- (void) setMyString: (NSString *) str {
[str retain];
[myString release];
myString = str;
} // the ordering of these retains and releases are important.
// example, if myString == str already, if we released myString before retaining str, then we might dealloc the string
 
In the long version, would you want to do a nil check before releasing myString? Not being picky, but my apps do tend to be.
 
Pointers in C are a massive source of confusion for newbies who have come from Java. My last question about this is that is the reason why pointers are used to hold objects' address instead of normal variables being used to hold them directly that the object can be assigned to other pointers without changing the object? (and primitive types do not need pointers because there is no harm from copying them, as they can not be changed).
 
Pointers in C are a massive source of confusion for newbies who have come from Java. My last question about this is that is the reason why pointers are used to hold objects' address instead of normal variables being used to hold them directly that the object can be assigned to other pointers without changing the object? (and primitive types do not need pointers because there is no harm from copying them, as they can not be changed).

Pointers are used to pass by reference rather than value so when you are passing around a struct it makes much more sense to pass a pointer around (and thus pass by reference) than it does to pass the struct around (thus copying it and passing by value).

You still seem to be confused though. A pointer is just a memory address. An int or a float or a char is used to hold a value where as an int * a float * or a char * are used to hold the address of that value.

Also don't forget that it is perfectly possible to have pointers to functions as well which allow you to do callback functions (qsort() is the famous example often used for function pointers). You can think of them in the same sort of light as delegate methods in Objective-C which when you get down to it are basically just callback functions.

Pointers to primitive types are just as useful. For instance pointers (pre-C99 anyway) where the only method to have dynamically allocated arrays. Also because C has no concept of a string you normally end up using malloc to and thus char * to pass around various null terminated strings.

Edit:

Think of it this way.

You have a house and you want to give your friend a copy of it. This is an extremely expensive operation as they would need to take the designs and then build a copy.

You have another friend who you just want to tell how to get to your house, so you give them your address.

You then decide to change the paint job on your house. The person who copied your house still has the old version as they have not repainted their house yet. You have not changed the address of your house though so the person who you gave your address too will end up at the house with the nice new paint job.
 
In the long version, would you want to do a nil check before releasing myString? Not being picky, but my apps do tend to be.

In Objective-C, sending any message including "release" to a nil-object is guaranteed to have no effect at all; if the message is supposed to return a value then it will return zero/NO/0.0/nil, whatever is appropriate.

So if an object is nil, then [anObject release] has no effect and is safe.
 
Pointers in C are a massive source of confusion for newbies who have come from Java.
They are generally a massive source of confusion for everyone that first encounters them. Having your experience colored by another language doesn't help, but they will make sense eventually. I would recommend a short amount of time with plain C getting used to the general syntax and figuring out concepts like pointers before diving headlong into Objective-C. Others disagree with this, but I feel like a foundation in C will serve you well outside of the context of Objective-C.

My last question about this is that is the reason why pointers are used to hold objects' address instead of normal variables being used to hold them directly that the object can be assigned to other pointers without changing the object? (and primitive types do not need pointers because there is no harm from copying them, as they can not be changed).

There's a lot going on there. I'll try to break it down. The first part:
... the reason why pointers are used to hold objects' address instead of normal variables being used to hold them directly
This was a design choice in Objective-C. There are languages (C++, surely others) that do let you choose if you want a "local" Object. In C++ they can simply be declared:
Code:
std::string myString = "Test";
The assignment part of this is more tricky than it seems, invoking
Code:
string& operator= ( const char* s )
, but anyhow... C++ also lets you have pointers to Objects like Objective-C. I like having pointers to Objects only, because it means EVERY Object you're dealing with is off in the heap, you know you have a pointer to it, you know exactly how to deal with it. In C++ you need to know if you have a std::string * or just a std::string, and must apply different operators to invoke methods, etc.

I can imagine you might then question, if Objective-C were to only pick one, why pick pointers? My opinion on this is the great expense that can be incurred in copying a large object around when it needs to be passed to a function (if you only have Object "values", this is what you'd have to do), assigned to another local instance, etc. Every instance variable has to be copied, etc. And what if you have Objects that are instance variables of other Objects? Then copying the parent will mean copying the child. That could get very, very expensive. With pointers only, if you just want another pointer to the Object, the assignment of a 4 or 8-byte pointer is very cheap. If you really DO need a copy, there are explicit methods to make one, so you get to control when you really need this behavior.

There is also a LOT more space on the heap than on the stack. This means that if you wanted to have an array of 200 Objects in a method, you'd use the size of all of the Objects ivars, and however the system stores function pointers for its methods, etc. taking up memory * 200. You could very easily overwhelm the stack, get a stack overflow, and have your program die. You'd have to break things into extremely small bits to deal with the inability to stick your Objects on the heap.

So Objective-C has a heap-only, pointer-only Object system. I like this, I'm sure some people don't. However, this really isn't different from Java at all. You just don't deal with the pointers explicitly in Java. But it does do pointer-only, heap-only Objects, too. You just don't see *s everywhere, the pointers are implicit in Java.

So now the next part, that I had a little more trouble understanding:
... the object can be assigned to other pointers without changing the object?
I'm not sure what you're asking, but I'll try to answer one interpretation, which is that you want an easy "copy" mechanism for Objects that just uses the = operator. This is a result of the compromises of the language design that I discussed above. There is an easy way to make copies, though:
http://developer.apple.com/mac/libr...Reference.html#//apple_ref/occ/intf/NSCopying
Many Objects will implement this protocol, and allow for a simple [myObject copy] message to be sent to an Object. You can just assign the result of this to another Object * and get the result you're looking for.

primitive types do not need pointers because there is no harm from copying them, as they can not be changed
I am having trouble understanding what you mean here, too. Primitive variables can be changed, that's the whole point. I'm sure that's not what you meant, though. The real issue here is that primitive types have a well-understood size, and it is pretty small. The largest I can think of might be 16-bytes. Copying 1,2,4,8, or 16 bytes around is pretty trivial. Copying around a few thousand may not be, in the case of a very large Object. It's also pretty important to have a type to assign literals to.

One could certainly imagine a system like Java stripping out primitives like int and short and replacing them with their object equivalents Integer and Short, then taking literals like 5 and simply replacing that with a fixed Integer object with the value 5 stored, but this seemed to even be outside of the Object-Oriented-only design of Java. People love primitives, and for things like loop control variables, it seems overkill to use Objects. Also, x + y where x and y are ints is pretty straight forward. If they were Integers, an Integer method would have to be invoked that would return a new Integer Object. It seems like a lot of overhead.

On your road to understanding pointers, you really need to not think of them as a different sort of thing than other primitives. I would just ignore Objects and pointers to them in Objective-C for now. Just deal with the concept in C. A pointer is a primitive type whose value is a memory address. An int's value might be 4 or 2334235, a char's value might be 'A' or '%', etc. A pointer's value might be the address 0x87432309 on a system with 32-bit addresses. If the pointer is of type int *, the integer value stored in the 4 (normally, sometimes 8) bytes starting at memory address 0x87432309 might be 7. A pointer is just a few bytes (enough to store a memory address on a specific system) that stores memory addresses. That's it. There's no magic.

There are a few special operators that you can apply to deal with pointers, because otherwise you really couldn't do anything with the memory address values they store. These operators are:
* This operator dereferences a pointer. So if you have an int *, when you apply this operator to it, you get an int with the value stored at the address your int * points to. This is, unfortunately, the same operator used for multiplication when applied to primitive numeric types, but this is a unary operator (takes only one operand, instead of two).
& This operator gives you the address of a variable. So if you have an int and apply & to it, you get an int * whose value is the address in memory where the int variable is stored.

Once you DO graduate to dealing with Objective-C, when you have an Object pointer you can just forget about these. The only operator applied to Object pointers is the message pass, []. You cannot dereference an Object pointer because, as we discussed earlier, there are no plain Objects in Objective-C. You cannot have an NSObject, only an NSObject *. You CAN get an address of an Object *, but then you just have an Object **, which is pretty rarely used. It comes up, normally with NSError values, but don't worry about that right now.

Please spend a few days getting used to pointers in plain C. Write a few programs, print out the pointers with the %p format specifier for the printf family, pass them to functions, print the pointer's value and the value stored at the address they hold, etc. Declare an int, and an int * and assign the address of the int using & to the int *, then change the int with an assignment statement, then display the value pointed to but the int *, etc.

This will click. It may take an hour, it may take a few days, it may take a few weeks. But this is critical to the understanding of how memory is used by your program, where your variables are being stored, and how to effectively program and deal with APIs you come across that expect to be passed things by reference (using a pointer).

Cromulent mentioned function pointers, which are great, but I wouldn't worry much about those for now. Focus on pointers to primitive types in plain C now, then deal with some Objects in Objective-C, and tackle function pointers when you need them. His point is good, but you should bite off a small chunk at a time if you're already a bit perplexed.

Good Luck!

-Lee
 
Cromulent mentioned function pointers, which are great, but I wouldn't worry much about those for now. Focus on pointers to primitive types in plain C now, then deal with some Objects in Objective-C, and tackle function pointers when you need them. His point is good, but you should bite off a small chunk at a time if you're already a bit perplexed.

Good Luck!

-Lee

In fact, as long as you stay entirely within the bounds of Objective-C and Cocoa, you should never have to deal directly with function pointers. It may be helpful at some point to fully understand, but what is going on is really more important than how it is happening most of the time.
 
In fact, as long as you stay entirely within the bounds of Objective-C and Cocoa, you should never have to deal directly with function pointers. It may be helpful at some point to fully understand, but what is going on is really more important than how it is happening most of the time.

Not necessarily, quartz uses function pointers to have call back functions for things like stippling patterns.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.