How to instantiate a pointer in objective-c - objective-c

Suppose I have a pointer to type ICScannerDevice class for which I have allocated some memory. Now, I want to initialize it with the pointer of type ICDevice which is a parent class of ICScannerDevice.
How do I do this?
Is the following the correct method? I guess not!
ICScannerDevice* scannerDevice = [[ICScannerDevice alloc] init];
scannerDevice = (ICScannerDevice*)device; // device is a pointer to ICDevice.

Suppose I have a pointer to type ICScannerDevice class for which I have allocated some memory.
ICScannerDevice* scannerDevice = [[ICScannerDevice alloc] init];
You are mixing two things up here. Variables are created by declarations, a declaration can also contain an initialisation expression.
When you declare a variable space is allocated which can contain a value of the variable's type - whether that type is int, in which case the value would be a integer e.g. 42, or ICScannerDevice *, in which case that value would be a reference to an allocated ICScannerDevice object.
So the declaration:
ICScannerDevice* scannerDevice
provides all the space you need to store a value of type ICScannerDevice *. The initialisation expression you give:
[[ICScannerDevice alloc] init];
is in your case redundant (and wasteful), you do not wish to create an object of type ICScannerDevice and store a reference to that object in scannerDevice as you wish to store a totally different reference in your variable:
Now, I want to initialize it with the pointer of type ICDevice which is a parent class of ICScannerDevice.
scannerDevice = (ICScannerDevice*)device; // device is a pointer to ICDevice.
This is wrong as you state that device holds a reference to an ICDevice object. As the type ICDevice is a parent of ICScannerDevice a reference to an ICScannerDevice can be treated as one to an ICDevice - aka "upcast".
However a reference known to be an object of type ICDevice may or may not be to an ICScannerDevice it might be , say, to an ICPlotterDevice. So you cannot directly cast - aka "downcast" and assign.
You must first check you actually have a reference to an ICScannerDevice. You do this by checking whether the type of your referenced object, using method isKindOfObject:, is the type ICScannerDevice, and you obtain that type with the class method:
if ( [device isKindOfObject:[ICScannerDevice class]] )
{
// we have a reference to an ICScanner Device
scannerDevice = (ICScannerDevice *)device; // downcast and assign
...
}
else
{
// device references something other than an ICScannerDevice object
// handle this case
...
}
You also need to handle the case where the value stored in device is nil - i.e. it references nothing. You might just want to combine this with the test in the if and treat it as an ICScannerDevice reference:
if ( (device == nil) || [device isKindOfObject:[ICScannerDevice class]] )
or you may need to handle it some other way.
HTH

a pointer is a number that holds a memory address where the object is.
a pointer is(16/32/64 bit) and lives on the stack. just its content is on the heap.
therefore, you don't need to allocate any space for a pointer. Only for the content. Since - in your case - you get a pointer to existing content. Just copy the memory address:
ICScannerDevice* = (ICScannerDevice*)device; // device is a pointer to ICDevice.
NOTE: remember casts don't change the content! if device isn't really a ICScannerDevice but something else, that might crash later.

First, there's no point in allocating an object if you're immediately going to assign some other object to its reference.
Second, if device is not a ICScannerDevice, casting it as one is an error that may or may not cause you problems depending on what you do with it next.
So, the answer is: no, it's not really correct.
(To give you a better answer about what you should be doing instead would require a little more context about where device comes from and how you want to use scannerDevice.)

Related

Use ObjectiveC objects with malloc

I try to create double pointer to simulate two dimensions array to hold the ObjectiveC object
Here is my declare syntax:
BlockInfo.m
#implement BlockInfo
-(void)someMethod{
}
#end
Other.m file
BlockInfo** pt = (BlockInfo**)malloc(sizeof(BlockInfo*)*10);
for(int i=0; i<10; i++){
pt[i] = (BlockInfo*)malloc(sizeof(BlockInfo)*3);
}
Here are the errors:
Pointer point to non-const type 'BlockInfo*' with no explicit ownership
Application of 'sizeof' to interface 'BlockInfo*' is not supported on the architecture and platform
Any help would be appreciated!
First of all you should really recheck whether you need ids in a C array. You have done it? Okay, do it again. You still need it? Okay, go on reading.
1.
What's wrong in your code is that you try to allocate the instance with malloc(). Never do that. Use +alloc-init, use +new, use a convenience allocator, but always use the framework for instance creation. Beside the fact that you give the RTE the chance to register instance creation, it is easier to you, because otherwise you have to set up the proper infrastructure of the instance. And there is no reason to do instance creation via C's malloc().
2.
Beside this you can store instance references (expressions of type id) to C objects ("variables"). To be more precise: You do that all the time, because every reference to an instance is a C object ("variable"). Therefore you can use C arrays, too.
A type is a retainable object owner type if it is a retainable object pointer type or an array type whose element type is a retainable object owner type.
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#id20
The reason for this is that C does not allow copying the whole array (as with structs), so you have to assign every single reference, what you do in your code.
But there are some caveats:
ARC cannot really follow the instance's ownership, when the array loses its extent. So set every element to nil explicitly, before the extent of the array is lost.
Do not use memcpy() or a similar function to change values of the elements. ARC has no chance to release the reference stored before or to retain the newly stored instance.
When you assign a new reference to an element, the old one is released. Therefore at the very beginning you have to fill the whole array with nil. (For local variables this is done automatically. That's the reason, why strong local vars are initialized.) calloc() does this automatically for you.
Typically the elements shall be strong references. You have to specify this explicitly.
BTW: Stylistic: You can malloc an C array of type id*, because all object references has equal size. (And has to, obviously). You shouldn't cast a malloc()'s return value.
So something like this should work:
__strong BlockInfo** pt = calloc(10, sizeof(id));
for(int i=0; i<10; i++){
pt[i] = [BlockInfo new];
}
…
for(int i=0; i<10; i++){
pt[i] = nil;
}
It seems that you tried to compile with ARC enabled. Try passing -fno-objc-arc as a compiler argument.
Please read the Objective-C Runtime Reference or the Objective-C Runtime source code for further details.

What are difference between *a and **a in objective-c object?

I write the following code:
NSArray *array = #[#1, #2];
How to output *array and **array, and what is the difference between them?
There are some answers, but I think none of them are a real help to you, because they describe the technical meaning.
Let's have a look to the first declaration:
NSArray *array …;
When somebody talks about this code, you will find statements like array is an instance object of NSArray. Even every experienced Objective-C developer knows the real meaning of this statement, it is simply wrong. What is the correct statement?
A. The instance object of NSArray
An instance object has a state, basically a set of data stored. To do so, it needs memory, which is reserved while object creation. You do not deal directly with that, but it is done inside +alloc. This is done explicitly at runtime while the program is running ("on heap", "heap allocation").
… [NSArray alloc] … // Get memory for an instance object of type NSArray
You address such an object solely via its address, the number of the first memory cell of the occupied memory area. (Every memory cell has a number, called the address. Yes, it is similar to addressing inhabitants in a house via the number of the house in a street. Therefore you can imagine the memory as a very, very long street.)
But an identifier like array only exists at compile time and is removed when the program is compiled. Therefore it is obvious that an identifier like array never denotes an instance object.
Short version: An instane object is an area of memory and is solely addressed via the number of the first memory cell (location).
B. A pointer to an instance object (reference)
But if an instance object is addressed via its number at runtime, how can my code deal with it? The trick is that the number is stored in a variable. (Looking to the C standard that is not completely correct. They say that it is stored in an object. But these objects has nothing to do with Objective-C objects and I will focus on variables, a subtype of objects.)
So you can have a variable storing the memory location of an instance object. Such a variable is called a pointer variable. It is declared with an extra *. So
NSArray * array;
means: A pointer variable with the identifier array that stores the location of an instance object of the type NSArray.
(Addresses are numbers. They are integral numbers. Therefore there is a connection between pointer variables and integers. And you can apply calculations to that numbers, called "pointer arithmetics". In some Situations this is important for C developers, but not for you as an Objective-C developer.)
The memory for this variable is not reserved explicitly with +alloc, but implicitly when you enter the area of your code, where the variable is declared. (Not completely correct again, but enough for this explanation.) So let's have a look again to a very boiled down version of object creation:
- (void)method
{
NSArray *array = [NSArray alloc];
}
The right side of this statement reserved memory for the object instance and returns a number, the address of the memory area. This number is assigned to a reference called array. The memory for that reference (it stores something, so it needs memory) is reserved implicitly via its definition.
Pointers to objects are usually called references.
Short version: So array is a reference to an instance object, storing the address of the instance object.
C. A pointer to a pointer to an instance object
Okay, we have an instance object that occupies memory to store the object state, addressed via its memory location (address). Then we have a variable that stores that address, the reference array. You can address that via its identifier.
But sometimes it is useful – I will have an example below – to address the reference variable via its address, too. You can get the address of a variable using the address operator &.
&array
What you get is: The address of a variable storing the address of an instance object. The type of such a double indirection ("address of … address of …") is
NSArray ** array;
This is, because in a variable definition the * means "address of".
Short version: A pointer to a reference is a variable that stores the address of a variable that stores the address of an instance object. It is declared with **. (Yes, you can have more level of indirections … No, that is not easier to understand.)
D. Use cases for pointers to references
Usually you do not need such double indirections in Objective-C. But there is one important use case, an error out parameter. To understand that, we will look at a method with a single indirected parameter as you know is:
- (BOOL)methodThatCanProduceAnError:(NSError*)error
{
…
error = [NSError alloc] … // Create an error object and store its address to the reference variable error.
return NO;
…
}
This method should emit an error via its error parameter.
You "call" such a method with code like that:
…
NSError *error; // A reference variable pointing to an instance object of type NSError
error = nil; // I do not have an error, so it points to "nothing".
[anInstance methodThatCanProduceAnError:error];
What happens? You pass the address of an instance object to that method as an argument. You pass nil for saying "I have no error". This is quite clear, because the method should pass out a reference to an instance object.
So the interesting part is inside the method, when it creates the error object and tries to pass it out. This does not work!
In Objective-C arguments are always passed by value. That means, that the value of the argument in the "calling code" is taken and assigned to a new variable inside the "called code". This new variable is called a parameter variable. When the method tries to change the value of the variable
error = [NSError alloc] … // Create an error object and store its address to the reference variable error.
it solely changes the value of the variable copy inside the method. The new reference will never find the way out of the method and the variable error in the calling code is left untouched. In the "calling code", error still has its old nil value.
So we need a way to change the content of the reference inside the "calling code". We do that by passing the address of the reference to the method:
- (BOOL)methodThatCanProduceAnError:(NSError**)error // double indirection
{
…
*error = [NSError alloc] … // *error is a reference to an object
return NO;
…
}
First in the method head we declare a parameter variable that is double indirected: The address of a reference. Second we assign the address of an instance object to the location, error points to. (This is done by the *.) The assignment is not done to the parameter variable, but to the location, the parameter variable points to.
Therefore we can pass the address of the reference:
NSError *error; // A reference variable pointing to an instance object of type NSError
error = nil; // I do not have an error, so it points to "nothing".
NSError ** pointerToError = &error; // The address of the reference.
[anInstance methodThatCanProduceAnError:pointerToError];
Now the method changes the contents of the reference variable. The error is passed out.

Pointer to BOOL in Objective C

Code:
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
BOOL initial = YES;
[invocation setArgument:&initial atIndex:2];
Question:
Would it be possible to pass YES to setArgument:atIndex: without creating the temporary variable?
I was thinking that maybe there's a language construct I'm not aware of and/or constant in the runtime that is always YES that I can point to.
Thanks!
No, not in any clean, reliable way.
NSInvocation will dereference whatever pointer you send it and copy data of length specified by the method signature out of it. You need to have that information somewhere so you can get an address to it, and having the local variable as you have is the best way to do so.
The answer is no. A pointer must point to an address in memory. So first you must allocate that memory and then send the address of that allocated memory into the method. In the case of a primitive the memory allocated will be on the stack and with an object the memory allocated for the object will be on the heap and the address of that object will be stored on the stack. As for the error you are getting the void* parameter of setArgument:atIndex: seems to want an object and not a primivtive. Have you tried using a NSNumber to represent a bool. NSNumber comes with a numberWithBool: method.
A pointer must point to something(including garbage) or nothing(means the pointer being initialized to NULL). A pointer is an indirect reference to an object. If you don't have such an object for your pointer to point to, you may not need a pointer. You can simply call setArgument:NULL atIndex:2.
The case to use a pointer like that in your code is to pass an output parameter, whose value will be set in the function you call, and in this case, you probably don't need to initialize the parameter before passing it to the function, the function is supposed to take care of assigning correct value to it.
So in your case, if you didn't mean to use a output parameter, you only need to pass the primitive BOOL to the function, no pointer needed.
EDIT
I just took a look at the doc for NSInvocation. The answer is the same as others', NO.
You have to pass a pointer, which must point to an existing object for NSInvocation to work correctly.

Memory allocation of return address in C and Objective-C

In a C function, its locals's memory is allocated when the function is called, and deallocated when function is finished. What about for functions that return a value (e.g. int, string), when and where does the return address's memory is allocated and deallocated, and is it part of the call stack or the callee stack, or something else?
Consider the following example:
int* foo()
{
int _myInt;
return(&_myInt);
}
This example gets me completely confused as of how memory is allocated for the return address that return a pointer. Can someone please explain?
Same for C and Objective-C?
I don't know about Objective-C but, with standard C, return values are typically stored in registers.
When the function returns a pointer type, it is up to the developer to ensure the memory pointed to remains valid after the call.
Consider the following function:
char* GetStr()
{
char buff[50];
strcpy(buff, "Hello, World!");
return buff;
}
This function returns a pointer to local memory, which is deallocated when the function returns. Accessing that memory would constitute a bug with undefined behavior.
This also applies to your example, which is not valid. But since an int can fit in a register, you can simply do return _myInt; and return the value directly.
In Obj-C if you allocated an object via alloc call then the standard practice is to autorelease that object before returning and name the method is such a way that the caller knows that it is getting an autoreleased object. If the caller needs then it can retain that object again.
- (MyClass *)getMyAutoreleasedObject {
MyClass *obj = [[MyClass alloc] init];
return [obj autorelease]; // caller needs to retain if needed
}
And if you do not autorelease then you should name the method in such a way that the caller knows that it must release the returned object. This is a strictly followed convention in Obj-C.
In C, if you allocate memory in stack then that memory is not valid in caller.
int *func() {
int a[100];
return a; // invalid in caller
}
Your example has the same problem. The returned memory is invalid in caller. In this case you can allocate the memory dynamically and the caller needs to free that when done.
int *func() {
int *a = (int *) malloc (100 * sizeof(int));
return a; // caller must free(a)
}
Parameters are passed to a function, and return values are passed back to the caller. How that is done is totally up to the implementation. The language only requires that it works and has nothing to say about how to do it.
On systems with available registers and a hardware assisted stack, these are generally used for passing the values back and forth.
Different types might be treated differently, for example some CPUs have dedicated address registers that hold pointers, or separate floating point registers. In that case values of those types might be handled differently from integer or struct values.
The size of the values passed might also affect it, small value could fit in a register while larger values would not.
Note that a stack is not a requirement for an implementation, it just has to use some other method for organizing values and function calls.
In your example function, any use of the return value whatsoever will invoke undefined behavior, since the lifetime of the pointed-to object has ended. The only safe way to call this function is without using the return value so that it is immediately discarded.

Objective-c dealloc of boolean value

How would I dealloc a boolean value?
Deallocing it this way below gives me a warning: Incompatible pointer to integer conversion assigning to 'BOOL' (aka 'signed char') from 'void *'
- (void)dealloc {
self.booleanVar = nil;
[super dealloc];
}
Perhaps I should clarify, this is from a simple class inherited from NSObject.
I'm using the self.var = nil pattern that you see in Cocoa Touch classes. Let's say if it was an NSString* instead should I use self.var = nil or [var release] in the deallocmethod? I'm a little confused here.
You don't need to do it. It is not an object. This also explains the warning, as you're trying to assign a nil pointer (that's a NULL for objects basically) to a non-object.
Regarding your second question, yes. You can think of primitive variables as being part of the object, so when it's deallocated the vars will not exist anymore.
But when you have a NSString * in an object, it's just a pointer to another object. If you dealloc the former, the pointer will be deleted, not the NSString. No one might point to it, it's kind of lost in the air, occupying memory. So, before deleting the pointer, if you won't need the object anymore, you send it a release message. That's done in the dealloc method, since it's called to "delete" and object and thus is a good place to delete also every other object that has no use anymore.
You dont need to dealloc a BOOL, since BOOLs are really just a byte, which is a primitive data type. You only need to dealloc objects which have been allocated to memory.
First of all, if booleanVar is just a plain BOOL value, as in it is declared like so:
BOOL booleanVar;
then you do not need to free up any memory associated with it, since that memory is allocated and freed when the class that holds it is allocated and deallocated. So no code for booleanVar in dealloc will be fine.
However, if you are talking about a pointer for a BOOL, defined like so:
BOOL *booleanVar;
and what you want is to set this variable to a non-value, you should set it equal to NULL instead of nil, since NULL is for value pointers and nil is for object pointers (see: NULL vs nil in Objective-C).
However, if what you want is to free up the memory that the BOOL pointer points to, allocated with malloc or realloc, etc, then try the free() C function (see: http://www.cplusplus.com/reference/clibrary/cstdlib/free/).
What would really clear all this up is if you showed us the property declaration for booleanVar in the class interface, which would tell us exactly what you want to do and you would get an answer with complete certitude.