I'm reading a book called Java and C: Key Differences, Learn Objective-C for Java Developers. (my background is C#/Java so the concept of pointers and managed memory is new to me, so please bear with me)
In chapter 2, it explains pointers with this example:
int i = 1;
int *iptr;
iptr = &i;
*iptr = 2;
I understand the above, where *iptr is a pointer, it is assigned the memory location of i, also from the pointer iptr we can access the value iptr points to with the *iptr syntax.
Further down the book there is the following snippet:
//..
NSMutableString *z = [[[NSNutableString alloc]init] autorelease];
[z appendString:#"Zombie "];
//...
From my understanding of chapter 2, the line [z appendString:#"Zombie "] should have been [*z appendString:#"Zombie "] instead, as we want the actual NSMutableString, not to its pointer, to be sent the message appendString!? I know I'm wrong and there is something that I'm missing, please point me to the right direction.
Many thanks,
Giuseppe
In Objective-C, you always work with pointers to objects (you can't create an object on the stack). Messages are always passed to pointers (although that's only an abstraction -- more complicated things are done at the runtime level).
The simple answer is that the Objective-C syntax is not the same as plain C language.
Yes, an Obj-C object is defined with the normal C syntax since it's actually a pointer to a structure but is then used without the * operator while dealing with Objective-C instructions..
Actually nothing forbids the semantics of Objective-C from sending a message to an object through its pointer, so simply don't worry.
In any case this applies to every object but there are many typedefs (for example NSInteger) that wraps primitive o structured C types. They can be used in C either by directly working with them onto the stack, either by allocating them.
Probably you are not aware that
NSMutableString *z = [[[NSNutableString alloc]init] autorelease];
is the abreviated form of
NSMutableString *z;
z = [[[NSNutableString alloc]init] autorelease];
Probably now is clearer.
As mipadi said, in Objective-C you always deal with pointers to objects and not real objects (like sometimes in C++ for example)
The bracket notation [obj message] implies that obj is a pointer to an object. Thus * is to be expressed.
Related
This question already has answers here:
Objective-C and Pointers
(3 answers)
why most of the objects we create in iphone are pointers
(1 answer)
Closed 9 years ago.
I am new to Objective-C and come from a Java background. I have just gone over casting in Objective-C but the book I am using failed to explain the use of the '*'/pointer when casting. Here is the example they gave me:
myFraction = (Fraction *) fraction;
Aren't pointers for specific objects so they have their own unique memory location? So then why must I use a pointer when simply referencing a class? In this case, Fraction.
Thanks I hope this makes sense and I know this is a simple question that I should know and understand but I could find nothing explaining this.
The * symbol has multiple meanings (beside multiplication :):
Dereference (follow) pointers. This code follows pointer stored in pointerToInt and then assigns a value to it.
(*pointerToInt) = 5;
Declares a pointer type. When you write int * it means “reference to an integer”.
int x = 5;
int * xPtr = &x
Now, objects are a kind of structures, but we only manipulate with them via pointers. Never directly. This basically means, that 99% of time when you see * (and it's not multiplication :) it is the second case: a part of type declaration:
NSString * = pointer to NSString structure (you can't use NSString alone)
Fraction * = pointer to Fraction structure and Fraction structure is described in Fraction class
So it's not “pointer to the Fraction class”, but rather “pointer to structure of Fraction class”.
I will go a little further and answer your future question about two **. You may see this usually with NSError arguments that are defined like methodWithError:(NSError **)errorPtr.
Short story: int is to int * as NSError * is to NSError **.
Long story: If we cannot manipulate with objects directly (without pointers to them), the single pointer becomes standard part of declaration. Now what if we want to make indirect access to the object? We use double pointer! First * is required for object, second is for indirection.
NSError *error = nil; // Empty.
NSError **errorPtr = &error; // Reference to our local `error` variable.
[data writeToURL:URL options:kNilOptions error:errorPtr];
// That method uses: (*errorPtr) = [NSError errorWith...];
NSLog(#"Error: %#", error); // Our local error is no longer empty.
I believe pointers are weird when you come from Java. They are a bit of legacy from C, but they are not used in any crazy way.
The * symbol is simply syntax that's used when referring to pointers.
Here, myFraction, and fraction are both variables that hold pointers (they aren't objects themselves – in fact you never have variables that hold Objective-C objects, objects must always be referred to with pointers).
The (Fraction*) syntax describes a cast to a pointer-to-a-Fraction of the expression on its right (in this case the fraction variable).
Remember that a pointer is just a variable that holds a memory location.
In Objective-C, when you have an object, what you really have is a pointer to an object, that is, a variable whose value is the memory address where the object really is.
Casting a pointer to a pointer of another type has no effect at runtime (at least for objects). In fact all your objects could be of type (void *). The casting helps the compiler to know what kind of object the pointer is pointing to, and generate errors or warnings.
If these two little paragraphs don't make much sense to you right now, consider reading some basic information or tutorials on pointers. Understanding pointers can be challenging for a beginner or from someone transitioning form the Java world.
...failed to explain the use of the '*'/pointer when casting...
Pointers have little to do with casting, other than being part of a type specifier. Consider:
Fraction is a type -- for the sake of argument, let's imagine that it's the name of a class, and that Fraction is a subclass of another class called Number.
Fraction * is a pointer to an instance of the Fraction class. In Objective-C, you always use pointers to refer to objects, so you'll see a lot of variables with types of the form ClassName *.
Casting is simply a matter of telling the compiler that it should treat a variable as a certain type. So, let's say you've got a variable number of type Number * and you know that the object it points to is actually a Fraction. However, you can't use any of the methods that are specific to Fraction because, as far as the compiler is concerned, number is just a Number *. You can use a type cast to tell the compiler: "I know what I'm doing, and number is definitely pointing to an instance of Fraction, so please treat number as a Fraction *." You do it like this:
Fraction *f = (Fraction *)number;
But again, the * doesn't have any special significance in the casting operation beyond the fact that Fraction * is the type to which you're casting number.
It's quite easy get the class/address of an object as a string, using:
NSString* objectInfoString = [object description];
The string returned is something like <ClassName: fk10009567>, with the letters and numbers representing it's unique address in memory, as I understand it.
Or, for just the address, simply using a formatted NSString with the %p place holder.
NSString* addressString = [NSString stringWithFormat:#"%p",myObject];
Is it then possible to create a pointer from this string information?
For Example:
NSObject* foo = [[NSObject alloc]init];
NSString* fooAddressString = [NSString stringWithFormat:#"%p",foo];
Then, I'd like to be able to do something like:
NSObject* newFoo = [NSObject objectForAddressString:fooAddressString];
such that newFoo = foo is true.
The foundation APIs provide a specific mechanism for doing this, without using 'magic strings', although you could do it using stringWithFormat, I guess. (It would be somewhat fragile, as noted).
To get a pointer reference to the object:
//Value now contains a pointer to the object, be careful it doesn't become dangling
NSValue* value = [NSValue valueWithPointer:(__bridge void*) myObject];
To get the object back from the pointer reference:
//If not using ARC you can skip the (__bridge id) here, and change the above cast to just (void*)
MyObjectType* myObject = (__bridge id) [value pointerValue];
Fragility?
It was noted that using '%p' to obtain a pointer value is fragile - while all Objective-C implementations currently return a hex value, the implementation of this could change. In any case, there's a specific API to do it.
Consider also that saving a reference to a pointer is fragile by nature in any case: Having obtained a pointer its necessary to ensure that it doesn't become 'dangling' - meaning the object being referenced goes away before the pointer does. The same strategies as using the __unsafe_unretained (aka assign) memory option should be applied. (No automatic weak references here!)
There are certainly valid applications of this kind of thing, however they are quite specialized and it would be unusual to find yourself doing this in everday apps programming. (I gathered you were asking the question simply to get a deeper understanding of Objective-C - kudos for that).
What is a valid use of this technique?
One valid application is to keep a reference to an Objective-C object in a C++ class. The Box2d physics engine (C++) allows this to provide an integration point with various Objective-C sprite engines.
This does not seem something sane or good thing to do. Relying on the - description of an object is very, very fragile. Why would you need to recover the object from its description? If you want to serialize and deserialize objects, you can do that by implementing the NSCoding protocol. If you want to associate objects with indices or keys, you can use NSArray or NSDictionary, etc...
That said, however, you can make a pointer out of a string:
NSString *addr = #"0xbadf00d";
uintptr_t ptr = strtoull(addr.UTF8String, NULL, 0);
id obj = (id)ptr;
I was asked recently by one of my friends about the new bridge modifiers that became active under ARC. He asked me if I knew which ones to use in specific times and what the difference between the different __bridge modifiers were. He asked me,"so how do they work, when do I use them, how do I use them , and how do they work "under the hood" "?
Note: This was supposed to be a "Share your knowledge" type of question, where I answered the question myself, but I'm not sure I set it up properly.
Because I learned what they were and how they operated just recently, I want to share with anyone else who wishes to learn about the __bridge modifiers under ARC which can be a source of confusion due to the fact that toll-free bridging used to be accomplished with a simple cast.
It used to be that if you wanted to, say, cast your NSArray object to a CFArrayRef for any purpose, it could be done with a simple cast like so:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (CFArrayRef) myArray;
In this case, maybe you had an NSArray of colors and needed to cast it to CFArrayRef for using it with CoreGraphics to draw a gradient.
However with ARC, this will no longer work for you and you will receive this error:
Well what the heck does this mean!?!
Well it turns out, ARC doesn't like it when you do this kind of cast and will even give you a few "Fix it" solutions, which all seem to have that same __bridge keyword in them, so let's get right to them!
Under ARC we have 3 main __bridge modifiers:
__bridge
__bridge_retained ( which is partnered by the CFBridgingRetain function)
__bridge_transfer (which is partnered by the CFBridgingRelease function)
So we'll begin with __bridge. What is it? __bridge is just another way of saying: "Hey compiler, just give me my darn casted object!". The compiler will be happy to do so and return to you a casted object of your liking!
However, because you wanted a "freely" casted object like that, YOU are still responsible of releasing the memory for the originally allocated object. In this case, if I were to do this:
NSArray* myArray = [NSArray alloc]init];
CFArrayRef arrayRef = (__bridge CFArrayRef) myArray;
I am still responsible for releasing the myArray memory because it was the originally allocated object. Remember, __bridge just tells the compiler to perform the cast!! And because I am compiling under ARC, I don't explicitly have to call [-release] on the myArray object, ARC will do it for me!
Note, that the __bridge modifier works both ways! (Hence, toll-free bridging) and you can just as easily cast a CF object to an NS object the same way ( that is toll-free bridgeable!) like so:
CFArrayRef arrayRef; // allocate this arrayRef and give it a value later on
//... amazing code.....
NSArray* myArray = (__bridge NSArray*)arrayRef;
But since the CF object would be the originally allocated object, I must call CFRelease(whatever);
Now let's move on to __bridge_retained and its partner in crime CFBridgingRetain() . This __bridge modifier is geared EXPLICITLY towards transferring the ownership of an NS object TO A CF OBJECT (So we'll be expecting to manually CFRelease(whatever) this due to it being a CF type object)
Meaning, if I were to do my old scenario again, but this time with __bridge_retained:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (__bridge_retained) myArray;
the arrayRef object now has explicit ownership of the memory that used to be owned by the myArray pointer. Because now the CF type has ownership, I must release it myself using CFRelease(whatever);
So what role does the CFBridgingRetain() function play in all this chaos? It plays the same exact role as doing the cast we just talked about! Let's take a look at the function prototype for CFBridgingRetain:
CFTypeRef CFBridgingRetain(id x);
We can see, it pretty much just simplifies the whole (__bridge_retained) notion into one function! We're gettting back a CF object after "inputting" an NS type object! Radical! Yes, I know this is awesome! Too much coolness to take in one sitting! And yes, it also performs the memory "ownership" transfer.. how awesome!
And last, but by no means least, __bridge_transfer and the almighty CFBridgingRelease() !
__bridge_transfer works almost like the opposite of __bridge_retained. The __bridge_transfer modifier transfers the ownership of a CF object type to an NS object type.
So let's refer to the example that's been used throughout this to dissect it:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (__bridge_retained) myArray;
// at this point, arrayRef holds the ownership
// Let's add this new line to change things up a bit:
NSArray* otherArray = (__bridge_transfer NSArray*)arrayRef;
So what does this awesome little program that we just wrote exactly do?
Step 1: We allocated an NSArray
Step 2: We passed the ownsership of the array to the arrayRef object
// Before we continue to step 3, let's understand at this point arrayRef is the owner
Step 3: We re-transfer the ownership that USED to be owned by arrayRef back to an NSArray*
Because at this point, the otherArray pointer is the owner, it would seem sort of natural at this point to say [otherArray release] when we're done, right? Well this is where ARC kicks in and will take care of releasing that array for you!
And did you know it gets cooler? This __bridge modifier's awesome partner in crime:
CFBridgingRelease()
makes it that much cooler! CFBridgingRelease has this function prototype:
id CFBridgingRelease(CFTypeRef x);
And we see, this is exactly the same thing that happens when we cast with __bridge_transfer. And this function also transfers the ownership to the NS object! This is just fantastic!
Using the CFBridgingXXX functions maybe can make a little more sense at first, due to the fact that many objective-c programmers still have the notion of the NARC rule:
Everything that has been called with:
N ew
A lloc
R etain
C opy
must have a balancing -release call
So doing this:
NSArray* myArray = [[NSArray alloc]init];
// there's the A of NARC!
//(cleaned by ARC)
CFArrayRef arrayRef = CFBridgingRetain(myArray); // there's the R of NARC!!
//NSArray* other = CFBridgingRelease(arrayRef); // cleaned up by ARC
Can make the process of learning the __bridge casts easier due to the fact that the retain was matched with a release
If all this still may be confusing, think of it this way: You are a pointer to any NS object type. For the sake of consistency, let's say you're an NSArray pointer, that right now isn't pointing to anything. So you can sort of imagine that you, as the nil pointer, are standing in a bathroom with the lights turned off. ( The lights turned off represents that you aren't pointing to anything).
Then, later on in code, your programmer decides to assign you to a new NSArray. i.e, he/she says this:
you = [[NSArray alloc]init];
Suddenly, the lights in the bathroom you were standing in, have turned on! You're pointing to an object! Now in normal program execution, when you're done using the object, you release it. So in this case, when you're done using the bathroom, you turn the lights off.
But the program you're in, unfortunately, isn't very "normal". The programmer decided to use some CoreFoundation objects! Bleh!
And he writes this line of code:
CFArrayRef other = (__bridge_retained CFArrayRef) you;
So now what happens is that, another person walks into the bathroom at the same time you leave. Out of politeness, you don't turn the lights off because there's another person using the restroom and is responsible for turning the lights off when he/she leaves
In this case, because the new owner of the restroom is a CF object, the programmer must manually release it.
But what if he/she were to write this:
CFArrayRef ref = (__bridge CFArrayRef) you;
what happens here is that, another person just barged into the same restroom as you without even asking! How rude! On top of that he expects you to clean up after him too! So you, being a gentlemen/lady turn off the lights when both of you finish.
However, since you are an NS type object, ARC comes and cleans it for you :)
And finally, what if the programmer writes this:
you = (__bridge_transfer NSArray*)arrayRef;
What happens here is the exact opposite of the first scenario. Instead of you leaving the restroom at the same time as someone enters, you're the one who enters while the other person leaves
The same memory management rules apply. Since you took over "owning" the restroom, you must manually turn off the lights. And because you're an NS type object, ARC will do it for you... again :) Isn't ARC such a beauty!
I know this may seem a bit intimidating and confusing at first, but just work your way through it, read it again and you'll find out how incredible this ARC mechanism works!
Thanks everyone for reading! Hope this helped :)
Thanks to #rob mayoff and # Krishnabhadra for
all the extra help and suggestions!
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
objective c difference between id and void *
why most of the objects we create in iphone are pointers
According to Stanford university course, 2010/2011
Lecture 3
The guy made something strange there (at least for me), which is that
NSString *digit = sender.titlelabel.text;
Why is digit a pointer?
The type of your digit is id, which is just basically just a C pointer to a certain struct. All references to objects in Objective-C have this primitive type, regardless of the Class of the object. So the answer to your question is, unfortunately, because that's the way Objective-C works.
So whether you're declaring an NSString*, or an UITableViewController*, or MyClass*, your variable has type id. This is the primary means by which the language implements polymorphism. So, for example, the following declarations are equivalent:
NSString *digit;
id digit;
And it's true of method prototypes as well. These are equivalent:
-(UITableViewCell *)tableView:(UITableView)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-(id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath;
A variable of type id is not an object itself, it is a pointer to an object. It is the handle with which you manipulate an object. Objective-C does all of the class compatibility work at runtime.
Hope this helps. Any questions?
Updates
That's right: int, float, double, char, void, and the pointer combinations, are all C primitive types. You can and will still use these quite a bit, and they are just what they are in a C program. But Objective-C adds the id type as a way to bridge the gap between the primitive typing of C and the very high-level typing of objects by the Objective-C system. id itself is typedef'd as a pointer to a simple struct in objc.h. At the level of the compiler and the language itself, there really isn't too much meaning to the type. For example, you'll almost never declare an array of ids, certainly never perform any arithmetic with them.
In fact, it's not too far a stretch to say that Objective-C is just plain vanilla C with some added syntax (particularly, the square-bracket notation for method invocation), a few extra primitive types (id, IMP, SEL), and a big runtime library. It's this runtime library that handles all things Object-Oriented.
Anyway, to answer your question, when you're actually programming, you will most often (99% of the time) just use class names to declare your variables - NSString *, NSData *, UITableViewController *, and so on. And the compiler will know what you're talking about, and issue a warning if you write code that clearly tries to put an NSString* where an NSData* is expected. But the actual meaning of those types really exists only at runtime.
I've digressed a little, but I'm not sure where your understanding is failing you, so I thought I'd just explain things a bit. You might want to read Apple's The Objective-C Programming Language to get a feel for the language.
NSString is an Objective-C class and all object references in Objective-C are pointers. I would suggest reading through some of the documentation such as Learning Objective-C A Primer:
Notice the * in the first declaration. In Objective-C, object
references are pointers. If this doesn’t make complete sense to you,
don’t worry—you don’t have to be an expert with pointers to be able to
start programming with Objective-C. You just have to remember to put
the * in front of the variable names for strongly-typed object
declarations. The id type implies a pointer.
It's not a digit, it's the "text" from the label, which is (I'm guessing) a string of integers and such to express the time.
So, all NSString types are declared as pointers in Obj-c.
sender.titlelabel.text;
Returns a NSString *
Remember, it's the same as:
NSString *str = [sender.titlelabel getText];
Because text is too. Or more preceisly, because the getText message returns a pointer.
You can find an intersting about why it has to be a pointer:
NSString and Pointers
I Hope it will help you to understand it in a Objective-C way.
in my objective-c program (or, maybe, in debugging utility) I get a bizarre behavior.
I defined, but not allocated or initialized 4 instances of some class (let it be "Rectangle"):
Rectangle *left, *right, *bottom, *upper;
Right after this line, I expect that for all of my four objects will be null pointers (debugging in Xcode), but for one of them (concretely "upper") exist point to some memory location, and his properties is initialized with random values.
Does it normal behavior? If so, please explain me why. (I am a bit new to objective-c programming)
Objective C does not (in general) guarantee that stack values are zeroed. It does guarantee that all ivars in an object are zeroed. Also, under ARC it does zero stack vars that it knows are objects. So the behavior you are seeing is correct assuming you are not using ARC.
In general, even if you are in an environment that zeros the value you should explicitly zero it in case your code gets reused somewhere else. If there is a constraint your code needs to work you should either satisfy it, test for it at runtime, or test for it at compile time (assert()).
As for why this is the case, it is that way because C behaves that way, and C traditionally has done it because it is bare metals and prefers to let the compiler have a lot of liberty in order to do performance optimizations. Objective C only differs in places where it needs to in order to support its own (supplemental) functionality.
Pro-tip: Never assume anything. It is good practice to initialize all your variables to a known value; in this case, nil.
If you are coming from another high-level language that does initialize variables for you, well... this isn't that language. :-)
You should do this...
Rectangle *left = nil;
Rectangle *right = nil;
Rectangle *bottom = nil;
Rectangle *upper = nil;
which is the same as
Rectangle *left = nil, *right = nil, *bottom = nil, *upper = nil;
Use ARC, its amazing as memory management isn't handled by you anymore!