Char * vs NSString * - objective-c

I am trying to get rid of some confusion when working with C.
Is using char *name in some sense the same as working with NSString *name in the sense that the pointer still points to the first memory allocation for it?
Ofcourse NSString has a bunch of extras but that isnt what I mean, will working with char *name allow me to work as if it was a NSString *name, so that I could in the future just work with the pointer "name" ?

The answer is no.
char* is meant to point to a simple array of (or single) char data values.
char* myCharPtr = "This is a string.";
//In memory: myCharPtr contains an address, e.g. |0x27648164|
//at address 0x27648164: |T|h|i|s| |i|s| |a| |s|t|r|i|n|g|.|\0|
On the other hand, NSString *name will be a pointer to an object which could have lots of extras, and you can't rely on where the actual character data is stored, or how. It is not encoded as ASCII (Sherm Pendley down below said it's UTF-16), and it could have extra data like the string's length, etc.
NSString* myStringPtr = #"This is an NSString.";
//In memory: myStringPtr contains e.g. |0x27648164|
//at address 0x27648164: |Object data|length|You don't know what else|UTF-16 data|etc.|
You alter and access unknown objects through their exposed methods because you don't know how they are formatted in memory, and thus can't access their data directly. (Or because they encapsulate themselves to hide it from you.)
You can still use the NSString pointer in future if you declare it as NSString *name though. This is what I mean:
NSString *name = #"This is a string.";
NSString *sameName = name; //This is pointing to the same object as name
NSLog(#"%#", sameName); //This prints "This is a string.", and if NSStrings were mutable, changing it would change name as well.
//They point to the same object.

char* and NSString* are two completely different implementations of strings.
NSString can only be used in Objective C (not in plain C), represents immutable strings, is based on Unicode characters and - being an object-oriented class - provides many methods. Furthermore, they are reference counted and always allocated on the heap.
char* is just any array of bytes, whose encoding is not well defined, it's mutable and it isn't object-oriented. char arrays can be allocated on the heap (with malloc) or on the stack. The former requires a call to free, while the latter must never be freed.

Is using char *name in some sense the
same as working with NSString *name in
the sense that the pointer still
points to the first memory allocation
for it?
I think you should regard the NSString* name as a handle to the object rather than a pointer to the object and as such not assume it points to the first memory allocation. I think that would be a better metaphor.

No,
char * is a pointer to an array of characters. NSString is a pointer to an NSString object. I cannot find any documentation of it, but I believe that NSString boxes a char *. Doing name[1] against NSString *name would refer to the 2nd element of an array of NSString objects.

In a sense - a somewhat non-useful sense, to be sure - they are the same, in that both are pointer types that refer to a memory address. That similarity turns out to be not very useful in practice though. To make use of either one, you have to take into account the type of "thing" they point to, and how one uses an array of char and an NSString instance is entirely different. Even for something as simple as assignment, one needs to handle the NSString instance in accordance to Cocoa's memory-management rules, using either -copy or -retain instead of a simple "foo = bar" assignment.

Related

array of char * in objective c

I have a c string and need it to break it up into lines (I wont make a NSString of them at this moment).
Is there something like an NSMutableArray where I can put this char * in?
Or how can I achieve it to make something from the strings what I can access later by index?
Currently I make
char *cline = strtok(data, "\n");
while(cline)
{
...
}
Or is it easier todo this when I read the file from disk?
Use an NSValue to store your char* in an NSMutableArray
Overview
An NSValue object is a simple container for a single C or Objective-C data item. It can hold any of the scalar types such as int, float, and char, as well as pointers, structures, and object ids. The purpose of this class is to allow items of such data types to be added to collections such as instances of NSArray and NSSet, which require their elements to be objects. NSValue objects are always immutable.
You cannot insert a C/C++ pointer into an NSMutableArray, unless it is wrapped in a container like an NSValue or other Objective-C class.
It would be a lot easier, if you want an NSMutableArray, to just convert it to an NSString.
NSArray* strings = [[NSString initWithCString:data encoding:NSUTF8StringEncoding] componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]];
Your other options, if you strictly want to stay in the C/C++ realm would be to have a vector of strings or an array of char*.
As others have already pointed out, to store primitive C types such as a in an Obj-C object such as an instance of NSMutableArray, you would need to wrap them in NSValue objects first.
As an alternative to doing this - if you are wanting to work with pure C strings in Obj-C, don't forget that you can freely mix C with Objective-C source code, so using a normal C array is a perfectly legitimate solution too.
By wrapping the values into an obj-c array you gain the bounds checking and mutability, but if you keep unwrapping the values to work on them as a C string, you might be better sticking with a plain old C string to begin with, to save the overhead.
If you then want to make an NSString, you can simply use the NSString convenience method stringWithFormat:, like so:
char str[50];
// read characters into the buffer from a file...
// When done, convert to an NSString:
NSString *string = [NSString stringWithFormat:#"%s", str];

Using malloc to allocate an array of NSStrings?

Since NSSstring is not defined in length like integer or double, do I run the risk of problems allocating an array of NSStrings for it using malloc?
thanks
ie:
NSString ***nssName;
nssName = (NSString***) malloc(iN * sizeof(NSString*));
the end result with for_loops for the rows is a 2D array, so it is a little easier to work then NSArray(less code).
No problems should arise, allocating an array of NSStrings is like making an array of the pointers to string objects. Pointers are a constant length. I would recommend just using NSArray but it is still fine to use a C array of NSStrings. Note that this may have changed with ARC.
Here is completely acceptable code demonstarting this:
NSString** array = malloc(sizeof(NSString*) * 10); // Array of 10 strings
array[0] = #"Hello World"; // Put on at index 0
NSLog(#"%#", array[0]); // Log string at index 0
Since NSString is an object (and to be more precise: an object cluster) you cannot know its final size in memory, only Objective-C does. So you need to use the Objective-C allocation methods (like [[NSString alloc] init]), you cannot use malloc.
The problem is further that NSString is an object cluster which means you do not get an instance of NSString but a subclass (that you might not even know and should not care about). For example, very often the real class is NSCFString but once you call some of the methods that treat the string like a path you get an instance of NSPathStore2 or whatever). Think of the NSString init methods as being factories (as in Factory Pattern).
After question edit:
What you really want is:
NSString **nssName;
nssName = (NSString**) malloc(iN * sizeof(NSString*));
And then something like:
nssName[0] = #"My string";
nssName[1] = [[NSString alloc] init];
...
This is perfectly fine since you have an array of pointers and the size of pointer is of course known.
But beware of memory management: first, you should make sure the array is filled with NULLs, e.g. with bzero or using calloc:
bzero(nssName, iN * sizeof(NSString*));
Then, before you free the array you need to release each string in the array (and make sure you do not store autoreleased strings; you will need to retain them first).
All in all, you have a lot more pitfalls here. You can go this route but using an NSArray will be easier to handle.
NSStrings can only be dealt with through pointers, so you'd just be making an array of pointers to NSString. Pointers have a defined length, so it's quite possible. However, an NSArray is usually the better option.
You should alloc/init... the NSString*s or use the class's factory methods. If you need an array of them, try NSArray*.
You should not use malloc to allocate data for Objective-C types. Doing this will allocate memory space but not much else. Most importantly the object will not be initialized, and almost as importantly the retain count for the object will not be set. This is just asking for problems. Is there any reason you do not want to use alloc and init?

Does #"some text" give an autoreleased or retain 1 object back?

Given this code:
// Initialize string
NSString *name = #"Franzi";
#"" macro creates a NSString with given text (here the name Franzi) and a RETAIN COUNT OF 1?
So #"" gives an NSString with have to be released or not? Am I responsible for this object?
Second code example then confuses me, even though I am using it that way:
NSSting *message;
message = [NSString stringWithFormat:#"Hello #%!",name];
//message = [NSString stringWithFormat:#"Hello Girl!"];
So message gets released in next run loop, k. But what is with the NSString given as argument for stringWithFormat?
Does the class object NSString release the NSString #"Hello %#"/#"Hello Girl" given as arguement?
Or does #""-Konstruktor only give back autoreleased NSStrings?
The NSString literal notation #"" gives you compile-time constant strings that reside in their own memory space and have constant addresses.
Contrary to popular belief, the reason why you don't release literal strings is not because they are part of the autorelease pool. They aren't — instead, they spend the entire application's lifetime in that same memory space they're allocated at compile time, and never get deallocated at runtime. They're only removed when the app process dies.
That said, the only time you need to memory-manage constant NSStrings is when you retain or copy them for yourself. In that case, you should release your retained or copied pointers, just like you do any other object.
Another thing: it's the literals themselves that don't need memory management. But if you pass them as arguments to NSString's convenience methods or initializers, like you do with stringWithFormat:, then it's those objects returned by the methods and initializers that follow all memory management rules normally.

Objective C, Difference between NSSting with "alloc" and without "alloc"

NSString *s1 = #"string1";
// NSString *s2 = [[NSString alloc]stringWithFormat:#"string2"];
NSString *s2 = [[NSString alloc] initWithFormat:#"string2"];
I know this is pretty basic concept but I am not 100% clear with this.
First one doesn't allocate a memory address and send one allocates a memory address...
Also second one increases the reference count of the variable but not the first one...
Even though I understand the concept but don't know the situation when I should use the first one or the second one..
When should I use the first one ? also when should use for the second one?
Thanks in advance..
Carl is is right, but there is some subtlety to keep in mind. Consider this:
NSString *s1 = #"string1";
NSString *s2 = [[NSString alloc] initWithString:#"string1"];
NSString *s3 = [NSString stringWithString:#"string1"];
NSString *s4 = [NSString stringWithFormat:#"string1"];
NSLog(#"ptrs %p %p %p %p", s1, s2, s3, s4);
The output is:
ptrs 0x1000010c0 0x1000010c0 0x1000010c0 0x100108da0
That's right; s1, s2, and s3 are all pointing to the same string instance while s4 ends up being a new instance. This is because NSString detects when a string is being initialized from a constant string and, when perfectly valid to do so, returns the constant string instead of bothering to allocate a new chunk of memory to hold the same thing. The stringWithFormat: case is not so optimized likely because all the potential format string processing makes such an optimization both moot and, likely, unnatural to the implementation.
In other words, do not assume that two strings are the same or different merely by code inspection or by pointer comparison. Use isEqual: or, better yet, isEqualToString:.
You should never use the second one - +stringWithFormat: is a class method. Including your first example, you have basically 3 choices:
NSString *s1 = #"string1";
NSString *s2 = [[NSString alloc] initWithString:#"string2"];
NSString *s3 = [NSString stringWithFormat:#"string3"];
s1 in this case is a pointer to a constant string. s2 and s3 both point to new strings that you've created, but s2 has been retained for you, and s3 has been autoreleased. If you just need a temporary object, the autoreleased object s3 or the constant object s1 are good choices. If you need to keep the string around, you should use s2 (actually now that I think about it s1 will work in this case too - it's not really idiomatic, though).
You can make s1 or s3 equivalent to s2 by sending them a retain message. You could also turn s2 into an equivalent object by sending it an autorelease message.
A string literal like #"string1" (or the #"string2" on the second line) is, as you've noted, not an allocation. The string is actually stored as a constant in your executable's data section, just like any constant you've declared. Strings created this way don't really have a reference count; you can send -retain and -release messages to them and nothing will happen.
Your second line is ill-formed; +stringWithFormat: is actually a class method, and it doesn't really make sense to use +stringWithFormat: without having any format parameters. In general, just use the string literal form if you don't have a specific reason to use another form. There's no need to allocate a new object if there's already the constant one floating around your application.
Don't use any ...WithFormat: method if you're just going to pass it a constant string. No need to parse the format string for the trivial case.

Please explain Objective-C instance definitions

NSString * aString;
What I don't understand is the *, what exactly does that operator do and what else can go there if anything?
Sorry I know this is a rather novice question but I am self taught; whenever I see "*" I think wildcard and I don't see why you would cast an object NSString ;
This means that aString points to where the NSString object is in memory. You might want to check out Binky Pointer Fun ( youtube version ) to get a hang of what Pointers are!
You can also read a bit more about pointers ( and even Double pointers! ) here.
A pointer is exactly what it sounds like, it's something that Points out where to go. Your memory is divided into "boxes" and each box is labeld with what we call a Memory Address. You you write:
NSString myString;
it means that you allocate an NSString object in memory. But when you decide to write:
NSString *myString;
it means that you create a Pointer to an NSString somewhere in your memory. In short it means that myString in the latter example will contain the Memory Address to the "real"
NSString object.
The * means that you are creating a pointer to an object. Note that this is part of the C language, not Objective-C (Objective-C is a strict superset of C).
http://cocoadevcentral.com/d/learn_objectivec/