As I understand pointers contain the address of data at another memory location?
When an app is running how is the location of pointers kept track of?
Why bother keeping track of the pointer, why not just directly keep track of address the pointer holds?
Additionally if I have the following code:
NSString *string = #"hello";
string = #"bye";
I am changing the value stored in the pointer named string (is it the pointer that is named string or the NSString object?) to the address of the new string ("bye"), right?
So how would I go about changing directly the object stored at the address held by the pointer?
(Also what is the correct terminology to use where I have used "keep track of"?)
Thanks
Why bother keeping track of the pointer, why not just directly keep
track of address the pointer holds?
Object references in objective C are actually pointers, so each time you use an object (such as NSString), you use a pointer to it - (NSString *)
I am changing the value stored in the pointer named string (is it the
pointer that is named string or the NSString object?) to the address
of the new string ("bye"), right?
Right.
So how would I go about changing directly the object stored at the
address held by the pointer?
In the case of such strings, they are immutable, and you can't change them, in case of other objects, you call their methods, or set their properties.
When an app is running how is the location of pointers kept track of?
Pointers are stored as any other variable; they typically take the same size as an unsigned long, but this is by no means guaranteed, just to give you an idea of how they are implemented. Compilers are free to do a huge variety of optimizations, so the pointers may be stored in memory, they may be stored in registers, or they may exist only as hypothetical entities if they are optimized away.
Consider the following code:
void foo(void) {
char *c;
char buf[100];
for (c=buf; c < buf+100; c++ {
c = '0';
}
}
In this case, the variable c is being used to write an ASCII 0 character to every character in the buf array. c may exist only in a register, because it does not live beyond this function. (There are better ways of writing this code.)
Consider the following code:
struct foo {
char name[10];
struct foo *next;
}
The member next in this case is a pointer to further struct foo objects -- say, a linked list of these things. These pointers must be stored in memory, because they are part of the contract of these objects -- they have to be there. There is no way around these pointers, either -- the objects they point to can be replaced with other objects on the programmer's whim. And, since the number of these objects is determined entirely at runtime, the compiler can't just keep track of the addresses in its symbol tables, as it would for stack-allocated variables.
So how would I go about changing directly the object stored at the address held by the pointer?
This is complicated by your example's use of "foo" strings in the code. These are saved in read-only memory in the process address space, so you cannot modify them. (Surprise!) If you initialize the strings with another method, you can modify the data via the pointer:
char *c = malloc(10);
strcpy(c, "hello");
c[0] = 'H';
printf("c: %s\n", c);
This will overwrite the h with H in the allocated space available via the c pointer. Accessing pointers as if they were arrays is the same re-writing the pointer access like this:
c[0] = 'f';
c+0 = 'f';
And, in fact, array accesses are pretty similar -- the name of the array is the same as a pointer to its first element.
It's a little complicated; the book Expert C Programming covers pointers in astonishing detail and is well worth the money.
Q : So how would I go about changing directly the object stored at the address held by the pointer?
Ans : start using NSMutableString if you want to change the content of memory location pointed by the your string pointer.
NSString is inmutable type ie you can't change the content but you can make the pointer to point somewhere else. "hello" to "bye" in your case.
Related
If I declare an NSMutableString
NSMutableString *str_value;
Why do I have to declare this as a pointer (using *)? If I don't, I get a compilation error.
Could someone explain this clearly?
Recall that Objective C is a superset of C. When you declare a variable without * in C, it is an indication that the memory for that variable is allocated either in the automatic storage if it is a local variable, as part of its outer structure if it is a member of a structure, or in the static memory if it is a static or a global. Using the typename or a structure tag without * in a parameter list of a function indicates passing by value.
The designers of the Objective C language could have taken the Java-like route, making every class instance is a pointer without the pointer syntax, but then the readers of programs in Objective C would need to know if a name represents a typedef based on a struct or an id type to answer even the most basic questions about objects of that type, such as if it is implicitly passed by pointer or by value, if it is allocated as part of the owning structure or as a heap object pointed to by a pointer inside the structure, and so on.
To avoid this kind of confusion, designers of Objective C decided to preserve the explicit pointer syntax for id objects.
A pointer means you are pointing / referencing to that class. Yes it will cause a compilation error, the reason for a pointer is mainly for memory. One data type (int or BOOL or float etc...) is only a few bytes, therefore it is not necessary to have a pointer. But NSMutableString and other Objective-C classes have a lot of properties and methods, with a lot of code. Therefore, since in your apps will have a lot of objects, which will use a lot of memory and thus slow down your app/decrease performance. Of course you should release the object once you make a pointer.
I'm working on a project that has C code embedded within Objective-C code. The C code produces some void * pointers that I would like to pass between Objective-C methods, so I'd like to wrap them in Objective-C objects to make an NSSet or something to that effect.
I have looked into NSData, which seems to accept arbitrary data, but wants to know the length of the memory chunk, that I don't have.
Any help is appreciated.
The NSValue class is usually used for this task:
NSValue* value = [NSValue valueWithPointer: myPointer];
and
void* myPointer = [value pointerValue];
Note, though, that the pointer given will not receive any special treatment with respect to memory management. You (and you alone) are responsible for making sure, that the memory it points to remains valid as long as pointers to that memory region exist and are reachable in some part of your program.
Note, though, that using such a value with NSSet or as key in a NSDictionary might or might not yield the intended effect:
NSData is essentially a byte buffer. It actually represents the content of the memory in question. Comparing NSData instances for equality compares at byte level. This is one of the reasons, NSData needs to know about the length of the memory region in question.
NSValue with a pointer value is an entirely different beast. Here, that actual (numeric) pointer value is the essential thing. No consideration is given (when comparing two NSValue instances) to the actual content at the address.
As the title suggests, I'm having trouble understanding exactly what a pointer is and why they're used. I've searched around a bit but still don't really understand. I'm working in Objective-C mainly, but from what I've read this is really more of a C topic (so I added both tags).
From what I understand, a variable with an asterisks in front points to an address in memory? I don't quite understand why you'd use a pointer to a value instead of just using the value itself.
For example:
NSString *stringVar = #"This is a test.";
When calling methods on this string, why is it a pointer instead of just using the string directly? Why wouldn't you use pointers to integers and other basic data types?
Somewhat off topic, but did I tag this correctly? As I was writing it I thought that it was more of a programming concept rather than something language specific but it does focus specifically on Objective-C so I tagged it with objective-c and c.
I don't quite understand why you'd use a pointer to a value instead of
just using the value itself.
You use a pointer when you want to refer to a specific instance of a value instead of a copy of that value. Say you want me to double some value. You've got two options:
You can tell me what the value is: "5": "Please double 5 for me." That's called passing by value. I can tell you that the answer is 10, but if you had 5 written down somewhere that 5 will still be there. Anyone else who refers to that paper will still see the 5.
You can tell me where the value is: "Please erase the number I've written down here and write twice that number in its place." That's called passing by reference. When I'm done, the original 5 is gone and there's a 10 in its place. Anyone else who refers to that paper will now see 10.
Pointers are used to refer to some piece of memory rather than copying some piece of memory. When you pass by reference, you pass a pointer to the memory that you're talking about.
When calling methods on this string, why is it a pointer instead of just using the string directly?
In Objective-C, we always use pointers to refer to objects. The technical reason for that is that objects are usually allocated dynamically in the heap, so in order to deal with one you need it's address. A more practical way to think about it is that an object, by definition, is a particular instance of some class. If you pass an object to some method, and that method modifies the object, then you'd expect the object you passed in to be changed afterward, and to do that we need to pass the object by reference rather than by value.
Why wouldn't you use pointers to integers and other basic data types?
Sometimes we do use pointers to integers and other basic data types. In general, though, we pass those types by value because it's faster. If I want to convey some small piece of data to you, it's faster for me to just give you the data directly than it is to tell you where you can find the information. If the data is large, though, the opposite is true: it's much faster for me to tell you that there's a dictionary in the living room than it is for me to recite the contents of the dictionary.
I think maybe you have got a bit confused between the declaration of a pointer variable, and the use of a pointer.
Any data type with an asterisk after it is the address of a value of the data type.
So, in C, you could write:
char c;
and that means value of c is a single character. But
char *p;
is the address of a char.
The '*' after the type name, means the value of the variable is the address of a thing of that type.
Let's put a value into c:
c = 'H';
So
char *p;
means the value of p is the address of a character. p doesn't contain a character, it contains the address of a character.
The C operator & yields the address of a value, so
p = &c;
means put the address of the variable c into p. We say 'p points at c'.
Now here is the slightly odd part. The address of the first character in a string is also the address of the start of the string.
So for
char *p = "Hello World. I hope you are all who safe, sound, and healthy";
p contains the address of the 'H', and implicitly, because the characters are contiguous, p contains the address of the start of the string.
To get at the character at the start of the string, the 'H', use the 'get at the thing pointed to' operator, which is '*'.
So *p is 'H'
p = &c;
if (*p == c) { ... is true ... }
When a function or method is called, to use the string of characters, the only the start address of the string (typically 4 or 8 bytes) need be handed to the function, and not the entire string. This is both efficient, and also means the function can act upon the string, and change it, which may be useful. It also means that the string can be shared.
A pointer is a special variable that holds the memory location of an other variable.
So what is a pointer… look at the definition mentioned above. Lets do this one step at a time in the three step process below:
A pointer is a special variable that holds the memory location of an
other variable.
So a pointer is nothing but a variable… its a special variable. Why is it special, because… read point 2
A pointer is a special variable that holds the memory location of an
other variable.
It holds the memory location of another variable. By memory location I mean that it does not contain value of another variable, but it stores the memory address number (so to speak) of another variable. What is this other variable, read point 3.
A pointer is a special variable that holds the memory location of an
other variable.
Another variable could be anything… it could be a float, int, char, double, etc. As long as its a variable, its memory location on which it is created can be assigned to a pointer variable.
To answer each of your questions:
(1) From what I understand, a variable with an asterisks in front points
to an address in memory?
You can see it that way more or less. The asterisk is a dereference operator, which takes a pointer and returns the value at the address contained in the pointer.
(2) I don't quite understand why you'd use a pointer to a value instead of
just using the value itself.
Because pointers allow different sections of code to share information, better than copying the value here and there, and also allows pointed variables or objects to be modified by called function. Further, pointers enabled complex linked data structures. Read this short tutorial Pointers and Memory.
(3) Why wouldn't you use pointers to integers and other basic data types?
String is a pointer, unlike int or char. A string is a pointer that points to the starting address of data that contains the string, and return all the value from the starting address of the data until an ending byte.
string is a more complex datatype than char or int, for example. In fact, don't think sting as type like int of char. string is a pointer that points to a chunk of memory. Due to its complexity, having a Class like NSString to provide useful functions to work with them becomes very meaningful. See NSString.
When you use NSString, you do not create a string; you create an object that contains a pointer to the starting address of the string, and in addition, a collection of methods that allows you to manipulate the output of the data.
I have heard the analogy that an object is like a ballon, an the string you're holding it with is the pointer. Typically, code is executed like so:
MyClass *someObj = [[MyClass alloc] init];
The alloc call will allocate the memory for the object, and the init will instantiate it with a defined set of default properties depending on the class. You can override init.
Pointers allow references to be passed to a single object in memory to multiple objects. If we worked with values without pointers, you wouldn't be able to reference the same object in memory in two different places.
NSString *stringVar = #"This is a test.";
When calling methods on this string, why is it a pointer instead of just using the string directly?
This is a fairly existential question. I would posit it this way: what is the string if not its location? How would you implement a system if you can't refer to objects somehow? By name, sure... But what is that name? How does the machine understand it?
The CPU has instructions that work with operands. "Add x to y and store the result here." Those operands can be registers (say, for a 32-bit integer, like that i in the proverbial for loop might be stored), but those are limited in number. I probably don't need to convince you that some form of memory is needed. I would then argue, how do you tell the CPU where to find those things in memory if not for pointers?
You: "Add x to y and store it in memory."
CPU: OK. Where?
You: Uh, I dunno, like, where ever ...
At the lowest levels, it doesn't work like this last line. You need to be a bit more specific for the CPU to work. :-)
So really, all the pointer does is say "the string at X", where X is an integer. Because in order to do something you need to know where you're working. In the same way that when you have an array of integers a, and you need to take a[i], i is meaningful to you somehow. How is that meaningful? Well it depends on your program. But you can't argue that this i shouldn't exist.
In reality in those other languages, you're working with pointers as well. You're just not aware of it. Some people would say that they prefer it that way. But ultimately, when you go down through all the layers of abstraction, you're going to need to tell the CPU what part of memory to look at. :-) So I would argue that pointers are necessary no matter what abstractions you end up building.
I know all instances of NSString are inmutable. If you assign a new value to a string new memory is addressed and the old string will be lost.
But if you use NSMutableString the string will always keep his same address in memory, no matter what you do.
I wonder how this exactly works. With methods like replaceCharactersInRange I can even add more characters to a string so I need more memory for my string. What happens to the objects in memory that follow the string? Are they all relocated and put somewhere else in memory? I don't think so. But what is really going on?
I know all instances of NSString are
inmutable. If you assign a new value
to a string new memory is addressed
and the old string will be lost.
That isn't how mutability works, nor how references to NSStrings work. Nor how pointers work.
A pointer to an object -- NSString *a; declares a variable a that is a pointer to an object -- merely holds the address in memory of the object. The actual object is [generally] an allocation on the heap of memory that contains the actual object itself.
In those terms, there is really no difference at runtime between:
NSString *a;
NSMutableString *b;
Both are references to -- addresses of -- some allocation in memory. The only difference is during compile time, b will be treated differently than a and the compiler will not complain if, say, you use NSMutableString methods when calling b (but would when calling a).
As far as how NSMutableString works, it contains a buffer (or several buffers -- implementation detail) internally that contain the string data. When you call one of the methods that mutate the string's contents, the mutable string will re-allocate its internal storage as necessary to contain the new data.
Objects do not move in memory. Once allocated, an allocation will never move -- the address of the object or allocation will never change. The only semi-exception is when you use something like realloc() which might return a different address. However, that is really just a sequence of free(); malloc(); memcpy();.
I'd suggest you revisit the Objective-C Programming Guide or, possibly, a C programming manual.
the NSMutableString works just like the C++ std::string do. i don't know exactly how they work, but there are two popular approaches:
concating
you create a struct with two variables. one char and one pointer.
when a new char(or more are added) you create a new instance of the struct, and add the address to the last struct instance of the string. this way you have a bunch of structs with a pointer directing to the next struct.
copy & add
the way most newbies will go. not the worst, but maybe the slowest.
you save a "normal" unmutable string. if a new char is added, you allocate a area in the memory with the size of the old string +1, copy the old string and concate the new char. that's a very simple approach, isn't it?
a bit more advanced version would be to create the new string with a size +50, and just add the chars and a new null at the end, don't forget the to overwrite the old null. this way it's more efficient for string with a lot of changes.
as i said before, i don't know how std::string or NSMutableString approaches this issue. but these are the most common ways.
I'll cut a really long story short and give an example of my problem.
Given a class that has a pointer to a primitive type as a property:
#interface ClassOne : NSObject
{
int* aNumber
}
#property int* aNumber;
The class is instantiated, and aNumber is allocated and assigned a value, accordingly:
ClassOne* bob = [[ClassOne alloc] init];
bob.aNumber = malloc(sizeof(int));
*bob.aNumber = 5;
It is then passed, by reference, to assign the aNumber value of a seperate instance of this type of class, accordingly:
ClassOne* fred = [[ClassOne alloc] init];
fred.aNumber = bob.aNumber;
Fred's aNumber pointer is then freed, reallocated, and assigned a new value, for example 7.
Now, the problem I'm having;
Since Fred has been assigned the same pointer that Bob had, I would expect that Bob's aNumber will now have a value of 7. It doesn't, because for some reason it's pointer was freed, but not reassigned (it is still pointing to the same address it was first allocated which is now freed).
Fred's pointer, however, has the allocated value 7 in a different memory location.
Why is it behaving like this? What am I minsunderstanding? How can I make it work like C++ does?
Edit:
Right, a fresh morning and I can see I gave a really bad, 5pm syndrome example.
What I'm trying to do is more like this:
#interface classOne : NSObject
{
int* numA;
}
#property int* numA;
#implementation...etc
numA is alloced and assigned a value. Later on, in a seperate thread (with necessary locks etc), this is done:
int* numB= malloc(sizeof(int));
*numB = 5;
free(RefToClassOne.numA);
RefToClassOne.numA = numB;
numA does get freed, but does not get assigned the value that numB is pointing to, which is the behaviour I would like.
Part of the longer story is that it is the vertex count for part of a vertex buffer that is passed into openGL. I realise that it shouldn't be a pointer, but the float* buffer for the coordinates is dealt with in the same way and needs to be of variable size, so I want to fix this to solve that problem also.
What you are misunderstanding is that (a) you cannot pass things by reference in Objective-C, and (b) even if you could, it wouldn't help you here.
Objective-C only allows you to pass things by value. Sometimes, as in the case of objects or pointers, the value you are passing is itself a reference, but it's being treated as a value. C++-style transparent references don't exist.
But suppose that we had them. How would that help in this case? The aNumber instance variable is still of type int*; when you assign to it (as in fred.aNumber = bob.aNumber), you must create a copy. At this point, it doesn't matter what was passed by reference, and nor does it matter that things are instance variables. Your code is effectively the same as
int* bobNumber;
int* fredNumber;
bobNumber = malloc(sizeof(int));
*bobNumber = 5;
fredNumber = bobNumber;
Here, bobNumber and fredNumber are different variables—they have different names, live at different locations in memory, etc.—that happen to have the same value. Now, the value they have is a reference to another location in memory, so they are equivalent references. However, what happens if we change one of them?
free(fredNumber);
fredNumber = malloc(sizeof(int));
*fredNumber = 7;
Since function arguments are passed by value, free can't do anything to fredNumber itself; it can only operate on fredNumber's value, freeing the referenced memory. Since this is the same as bobNumber's value, we see this effect if we try to dereference bobNumber. Next, we assign a value to fredNumber. Since fredNumber and bobNumber live at different locations in memory, this assignment naturally does nothing to bobNumber. At this point, fredNumber != bobNumber, so naturally when we assign 7 to *fredNumber, nothing happens to *bobNumber (which is invalid anyway, having just been freed).
Note that your comment about "making it work like C++ does" is strange; C++, like I said, doesn't work this way either. If you really wanted to make this work in C++, you would have to have a reference instance variable
class ClassTwo {
public:
int*& aNumber;
ClassTwo(int*& an) : aNumber(an) { }
};
Note that an needs to be passed by reference; I originally tried to do it without that, and then a copy was created in the constructor, producing the same old set of problems.
Now, whether or not we pass bob by reference, it will still have the same aNumber reference, so we can construct something like
int* shared;
ClassTwo bob(shared);
bob.aNumber = new int(5);
ClassTwo fred(bob.aNumber);
delete fred.aNumber;
fred.aNumber = new int(7);
And everything will work like you expect. However, this may well not be a good idea. For one reason why, note the shared variable—references need to be able to reference something. And this can produce problems: if the object being reference goes out of scope, the behavior of the reference is undefined.
If you set both to point to the same object then when you free the object you are effectively removing what both are pointing to so both pointers become invalid. In order to reassign you need to repeat the same procedure by setting both pointers to point to the same new object.
Destroying an object will not automatically update all pointers that point to it since the pointers are independent from each other and don't know anything about each other.
You are better off by creating a clone from the original instead of sharing the object in question so that each 'aNumber' points to its own copy.
I guess what you are after is like in C++ you write
fred = bob;
where fred creates a copy of bob
in that case you would need some kind of clone function in your class.
EDIT: rephrased
Well, as far as I can see your code is doing exactly what you are telling it to.
Using a pointer to an int isn't the most compatible way of handling a value; you will need to call free on it appropriately, and it would strike me as far simpler to use a NSValue object if you just want to pass the value between objects.
This works the same way in C++. Here's an equivalent example:
class Bob {
public:
int *aNumber;
};
void wontWork() {
Bob bob, fred;
bob.aNumber = new int;
*bob.aNumber = 5;
fred.aNumber = bob.aNumber;
delete fred.aNumber;
fred.aNumber = new int;
*fred.aNumber = 7;
cout << *bob.aNumber << *fred.aNumber << endl;
}
Do you expect *bob.aNumber to be 7 here? When you did delete fred.aNumber, that freed the memory that both bob and fred pointed to. Then you reassigned fred to point to new memory, but you did not reassign bob, so it's just a dangling pointer. So there's nothing that would cause bob to be 7. Remember, pointers are just plain value types like ints. There's no magic that causes two pointers pointing to the same address to sync up with each other.