views:

10339

answers:

4

I'm learning objective-C and Cocoa and have come across this statement:

The Cocoa frameworks expect that global string constants rather than string literals are used for dictionary keys, notification and exception names, and some method parameters that take strings.

I've only worked in higher level languages so have never had to consider the details of strings that much. What's the difference between a string constant and string literal?

+3  A: 

Let's use C++, since my Objective C is totally non-existent.

If you stash a string into a constant variable:

const std::string mystring = "my string";

Now when you call methods, you use my_string, you're using a string constant:

someMethod(mystring);

Or, you can call those methods with the string literal directly:

someMethod("my string");

The reason, presumably, that they encourage you to use string constants is because Objective C doesn't do "interning"; that is, when you use the same string literal in several places, it's actually a different pointer pointing to a separate copy of the string.

For dictionary keys, this makes a huge difference, because if I can see the two pointers are pointing to the same thing, that's much cheaper than having to do a whole string comparison to make sure the strings have equal value.

Edit: Mike, in C# strings are immutable, and literal strings with identical values all end pointing at the same string value. I imagine that's true for other languages as well that have immutable strings. In Ruby, which has mutable strings, they offer a new data-type: symbols ("foo" vs. :foo, where the former is a mutable string, and the latter is an immutable identifier often used for Hash keys).

Brad Wilson
A: 

I just wanted to add that I looked around via google, and it seems you defined constant strings by appending the @ before the literal, for example:

@"a constant string"

Also, I can't help but comment, many "higher level" languages have a similar concept, though the semantics may differ somewhat among different languages.

For example, Java and C# have the concept of a constant and literal string. In Java it is specified with the "final" keyword, and I believe C# uses the "const" keyword. This indicates that the variable will not be changed, and so it is "constant", meanwhile a literal is just a literal definition of a string, rather than constructing it by other means (such as using a constructor with a char array passed in).

Even dynamic languages can have similar concepts, such as Ruby with "symbols". A symbol in Ruby is a constant string in that there is only ever 1 instance of any given symbol, while a string can have multiple instances (and is mutable, unlike Java and C#).

Mike Stone
This isn't even in the vicinity of correct.
calmh
+26  A: 

In Objective-C, the syntax @"foo" is an immutable, literal instance of NSString. It does not make a constant string from a string literal as Mike assume.

Objective-C compilers typically do intern literal strings within compilation units — that is, they coalesce multiple uses of the same literal string — and it's possible for the linker to do additional interning across the compilation units that are directly linked into a single binary. (Since Cocoa distinguishes between mutable and immutable strings, and literal strings are always also immutable, this can be straightforward and safe.)

Constant strings on the other hand are typically declared and defined using syntax like this:

// MyExample.h - declaration, other code references this
extern NSString * const MyExampleNotification;

// MyExample.m - definition, compiled for other code to reference
NSString * const MyExampleNotification = @"MyExampleNotification";

The point of the syntactic exercise here is that you can make uses of the string efficient by ensuring that there's only one instance of that string in use even across multiple frameworks (shared libraries) in the same address space. (The placement of the const keyword matters; it guarantees that the pointer itself is guaranteed to be constant.)

While burning memory isn't as big a deal as it may have been in the days of 25MHz 68030 workstations with 8MB of RAM, comparing strings for equality can take time. Ensuring that most of the time strings that are equal will also be pointer-equal

Say, for example, you want to subscribe to notifications from an object by name. If you use non-constant strings for the names, the NSNotificationCenter posting the notification could wind up doing a lot of byte-by-byte string comparisons when determining who is interested in it. If most of these comparisons are short-circuited because the strings being compared have the same pointer, that can be a big win.

Chris Hanson
Mike is right. From the book "Programming in Objective-C 2.0" - "The string @"Programming in Objective-C is fun.\n" is an example of a constant character string object."
Josh Brown
"Programming in Objective-C 2.0" is not the language reference; citing it as if it were such is thus incorrect.In C, "foo" is referred to as a string literal. Typically "constant" refers to a pointer or variable, not a literal; literals are constant by definition.
Chris Hanson
A: 

Thank you for this excellent contribution. I am an Objective-C/Cocoa newbie and came to this article having just read Chapter 3 of the Cocoa Fundamentals Guide ("Cocoa API Conventions"). This gives another compelling example of why one would want to use global string constants. In particular, "the Cocoa frameworks expect that global string constants rather than string literals are used for dictionary keys, notification and exception names, and some method parameters that take strings. You should always prefer string constants over string literals when you have a choice. By using string constants, you enlist the help of the compiler to check your spelling and thus avoid runtime errors."

Thank you for showing how to do this. (I have now adopted this approach.)

PS. It also provides a single place where the string contents can be maintained.

Franz Posaner