Why does a pointer to an NSInteger multiply the value by 8? - objective-c

In my header, I declared a few variables as #property (nonatomic) NSInteger *soldWindows; and used them to keep track of counts, incrementing with _soldWindows++;. The result consistently came out 8 times what it should be. I figured out my problem was declaring it as a pointer, so I changed it to #property (nonatomic) NSInteger soldWindows; which solved my problem.
My question is, if it was just storing a memory address, why was the integer value scaled by 8 instead of being an arbitrary address?

A pointer points to a place in memory. When you increment a pointer like this, you increment the value of the pointer, to point to a new place in memory. Given this, you can use pointer arithmetic to iterate through successive elements in an array, by dereferencing an incremented pointer. So, you're not incrementing by 1, but rather, by the size of the type of your pointer. An NSInteger is nothing more than a 64 or 32 bit int, depending on platform. In this case, it seems to be 64 bits, which is 8 bytes. This is where your 8 bit "scaling" was coming from.
Conclusion: your fix is correct!

I declared a few variables as [...] NSInteger *soldWindows; and used them to keep track of counts.
You are misusing the concept of a pointer. In C, a pointer is the address of an object in memory. In your use case there is no object being pointed to—just the address that point's to nowhere.
While this is not a problem as long as you don't dereference the pointer it's still confusing (and does not help in any way). A simple integer (like int or NSInteger) is a better choice.
why was the integer value scaled by 8?
The reason for this is called pointer arithmetic. Every C pointer has a type. The type describes the object in memory where the pointer holds the address of. When you increment a pointer, the compiler actually adds the size of the object to the pointer, so that it points to the object right after the previous one.
The size of NSInteger (in 64 Bit iOS) is 64 bit = 8 bytes. That's why incrementing an NSInteger * actually adds 8 to it.

Related

Array of pointers returned my Malloc/Calloc in Objective-C

Let's say I have the following:
MyClass *__strong*matches = (MyClass*__strong*)calloc([myArray count], sizeof([MyClass class]));
If I would like to refer to the second pointer in matches, would I write matches[1] or would I write matches[4]? I am confused because I know that pointers take up 4 bytes, but my program crashes due to a memory error if I follow the logic of matches[4] and my program works perfectly when filling matches if I follow the logic of matches[1].
Furthermore, which would apply if I used malloc instead of calloc?
It is matches[1] because the compiler knows from the type (MyClass * __strong *matches) the size of the items (pointers in your case) that the pointer is pointing at and uses that to determine how to compile the index operation.
For comparison consider int x[4] vs. char y[4], indexing does not mean "byte offset 4" from the start of the array but "item 4" where item in this case is an int (probably 4 or 8 bytes) or char (1 byte). You have pointers (probably 4 or 8 bytes) in your "array" and the compiler knows that from the type.
HTH

pointer of a primitive datatypes objective c

I know this could be a dumb question.
I am totally confused about this, i accept i have not understood the basics properly. Why did
BOOL *booleanTest = (5 < 1)? YES : NO;
did not throw a compilation error, it is a primitive datatype and it cannot have pointer, what made it to compile and return yes always, irrespective of condition inside.
Please bless me with the reason and also why
int *magicNumber = value / 25;
did not throw a compilation error.
C is not as strictly typed as you apparently believe. Assigning an integer to a pointer is legal, though usually unwise. The compiler should have warned you that the assignment makes a pointer from an integer without a cast, though.
In both the cases you are declaring the variables and using them there itself without any sort of initialization.
I am assuming that you do not know the difference between declaration and initialization so during declaration the value of the variables is set to garbage or some random value. How that is assigned is because the memory cell that the pointer is pointing to is some random memory cell which was used by some other application which has left the value there.
Now what happens in the first case:
BOOL *booleanTest = (5 < 1)? YES : NO;
The pointer booleanTest is set to type BOOL and the value that it is pointing is only half a number that is required to point to a full memory cell. So it takes up the first few bits of the cell and which is probably 1 so it is coming to YES always.
In the second case
int *magicNumber = value / 25;
This won't cause any compilation error as it is legally allowed to store values inside a pointed value. It gets type casted to the exact variable type of the pointer.

Struct Pointer Not Providing the Correct Size in sizeof() method

I'm having a issue getting the size of a struct pointer after allocating the memory using malloc or realloc. I've worked around this by keeping track of the memory in a separate counter, but I would like to know if this is a bug or if there is a way to properly query the size of a struct pointer.
Sample code demonstrates that no matter how much memory I allocate to the struct pointer it always returns 4 when querying using the sizeof() method.
typedef struct {
int modelID;
int bufferPosition;
int bufferSize;
} Model;
Model *models = malloc(10000 * sizeof(Model));
NSLog(#"sizeof(models) = %lu", sizeof(models)); //this prints: sizeof(models) = 4
4 is the correct answer, because "models" is a pointer, and pointers are 4 bytes. You will not be able to find the length of an array this way. Any reason you're not using NSArray?
If I understand you correctly you want to get at the size of the allocated buffer.
sizeof if the wrong way to go since it is evaluated at compile time. The size of the buffer is a runtime concept.
You would need a way to query you C library to return the allocation size for the pointer to the buffer.
Some systems have a way to get that kind of information, for instance malloc_size on Mac OS.
4 is the correct answer.
Pointers point to a memory location which could contain anything. When you are querying the size of a pointer, it gives the size of the memory location which holds the pointer, which in your case is 4.
For example
int *a = pointing to some large number;
int *b = pointing to a single digit number;
In the above case, both a and b have the same size irrespective of where they are pointing to.
For more information, have a look at this post size of a pointer
sizeof(myvar) will return size of pointer. in 32bit environment it equals to 4(bytes).
why don't you use sizeof (Model) instead?

Size of NSArray

When I tried to check the size of NSArray which is declared without any capacity, I found it 4. Now the question is why it is always 4? please help me out to find it....
Thanks
If you're talking about sizeof, it is not the right way to find out how much data an NSArray is holding. Objective-C objects are always accessed through pointers, and the size of a pointer on the iPhone is 4 bytes. That's what sizeof is telling you. To find out how many objects are in an array, ask the array for its count.
Given this:
NSArray *foo;
NSLog(#"%d", sizeof(foo));
You'll either get 4 or 8, depending on if you are on a 32 or 64 bit system. Note that I quite purposefully didn't initialize foo; there is no need to do so as sizeof(foo) is giving the bytesize of foo and foo is just a random pointer to an object. Wouldn't matter if that were id foo; void*foo; NSString*foo; all would be 4 or 8.
If you want the allocated size of an instance of a particular class, the Objective-C runtime provides introspection API that can do exactly that. However, I can't really think of any reason why that would be more than passingly interesting in a program.
Note that the allocation size of an instance does not account for any sub-allocations. I.e. an NSArray likely has a backing store which is a separate allocation.
To reiterate:
sizeof(foo) in the above code has nothing to do with the size of the allocated instance.

Comparator based on integer addresses

I want to create a custom dictionary that does not copy its keys (just retains).
Internally, I plan to use an NSMutableArray with a special Pair object, where the first object of the pair is the key, and the second is the value.
Keys are all unique.
In order to quickly retrieve objects on keys, I'd use binary search algorithm - so the array should be SORTED (attention!) on memory addresses of pairs' first objects.
(btw, this is why I refused to use CFDictionaryRef with a special set of callbacks - I suspect it to degrade to O(n) in case when a reasonable hash would not be provided)
Is this a bad idea, assuming that:
Objects used as keys may change internally (that is, I cannot use isEqual: instead of address comparison);
Objects used as keys are NOT going to be deallocated (which is reasonable - they are retained by a special Pair object, and the Pair is retained by an internal NSArray).
Why is it bad (or good)?
How do I obtain memory address from a pointer? Just cast it to a long long int or something like that?
Thank you!
To get an integer value from a pointer, cast to intptr_t or uintptr_t. These types are defined in <stdint.h> and are explicitly guaranteed to be large enough to hold the value of a pointer.
I assume that pointers in objective-c are similar to c/c++. I have built sorted arrays of memory addresses to use for looking up a stack trace. On a 64 bit machine, it should be cast to whatever scalar variable is 64 bits, probably a long int. Or if you can use a uint64_t type, it will guarantee the correct size. For a 32 bit machine, use an unsigned 32 bit integer, or a uint32_t. You can use the > < >= <= = and - operators on pointers and you can also use the + operator with a pointer and an integer.