What is the difference between a string constant and a string literal?

I am studying objective-C and Cocoa and came across this statement:

Cocoa frames expect global string constants, not string literals, to be used for dictionary keys, notification and exception names, and some method parameters that accept strings.

I only worked in languages ​​of a higher level, so I never had to often understand the details of strings. What is the difference between a string constant and a string literal?

+57
string objective-c
Aug 25 '08 at 7:54
source share
3 answers

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 suggested.

Objective-C compilers usually execute static literals in compilation units, i.e. combine several uses of the same string string, and it is possible for the linker to perform additional internment between compilation units that are directly linked to a single binary file. (Since Cocoa distinguishes between mutable and immutable strings, and literal strings are always immutable as well, this can be simple and safe.)

Lines

A constant , on the other hand, is usually 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 syntax exercise here is that you can use the string efficiently, ensuring that only one instance of this string is used even for multiple frameworks (shared libraries) in the same address space. (The placement of the const keyword is important; it ensures that the pointer itself is constant.)

While the memory record is not as large as it was in the days of 25MHz 68030 workstations with 8 MB of RAM, string comparison for equality may take some time. Ensuring that most of the time series that are equal will also be equal to the pointer.

Say, for example, that you want to subscribe to notifications from an object by name. If you use inconsistent strings for names, sending an NSNotificationCenter message can result in a lot of byte byte string comparisons when deciding who is interested in it. If most of these comparisons are shorted because the compared strings have the same pointer, this can be a big win.

+81
Aug 25 '08 at 8:51
source share

Some definitions

A literal is a value that, by definition, is immutable. e.g. 10
A constant is a read-only variable or pointer. for example: const int age = 10;
A string literal is an expression of type @"" . The compiler will replace this with an instance of NSString .
String constant is a read-only pointer to an NSString . for example: NSString *const name = @"John";

Some comments on the last line:

  • This is a constant pointer, not a constant object 1 . objc_sendMsg 2 doesn't care if you qualify an object with const . If you want an immutable object, you must encode this immutability inside object 3 .
  • All @"" expressions are truly immutable. They are replaced with 4 at compile time with instances of NSConstantString , which is a specialized subclass of NSString with a fixed memory layout of 5 . This also explains why NSString is the only object that can be initialized at compile time 6 .

A constant string will be const NSString* name = @"John"; , which is equivalent to NSString const* name= @"John"; . Here both syntax and programmer intentions are wrong: const <object> ignored, and the instance of NSString ( NSConstantString ) is already unchanged.

1 The const keyword is applied to what is immediately to the left of it. If nothing is left of him, this refers to what is immediately on the right.

2 This is a function that the runtime uses to send all messages to Objective-C, and therefore that you can use to change the state of an object.

3 Example: in const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const does not prevent the last statement.

4 The LLVM code that rewrites the expression, RewriteModernObjC::RewriteObjCStringLiteral in RewriteModernObjC.cpp.

5 To see the definition of NSConstantString , cmd + click it in Xcode.

6 Creating compile-time constants for other classes will be simple, but a specialized subclass will be required for the compiler. This will break compatibility with older versions of Objective-C.

sub>




Back to quote

Cocoa structures expect global string constants, not string literals, to be used for dictionary keys, notifications, and exception names and some method parameters that accept strings. You should always prefer string constants over string literals when you have a choice. Using string constants, you will enlist the help of a compiler to check your spelling and, therefore, avoid runtime errors.

It says that literals are error prone. But he does not say that they are also slower. Compare:

 // string literal [dic objectForKey:@"a"]; // string constant NSString *const a = @"a"; [dic objectForKey:a]; 

In the second case, I use keys with constant pointers, so instead of [a isEqualToString:b] I can do (a==b) . The implementation of isEqualToString: compares the hash and then runs the C function strcmp , so it is slower than comparing the pointers directly. Which means why constant strings are better: they compare faster and are less error prone.

If you want your constant string to be global, do the following:

 // header extern NSString *const name; // implementation NSString *const name = @"john"; 
+12
Sep 08 '12 at 2:50
source share

Let me use C ++ since my goal C is completely absent.

If you insert a string into a constant:

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

Now when you call the methods, you use my_string, you use the string constant:

 someMethod(mystring); 

Or you can directly call these methods with a string literal:

 someMethod("my string"); 

The reason, apparently, is that they encourage you to use string constants because Objective-C does not perform “interning”; that is, when you use the same string literal in several places, it is actually a different pointer pointing to a separate copy of the string.

For dictionary keys, this is of great importance, because if I can see that two pointers point to the same thing, it is much cheaper than doing a whole string comparison to make sure that the strings have the same value.

Edit:. Mike, in C # strings, immutable and literal strings with the same values, all ending, pointing to the same string value. I assume this is true for other languages ​​that have immutable strings. In Ruby, which has mutable strings, they offer a new data type: characters ("foo" vs .: foo, where the former is the mutable string and the latter is the immutable identifier often used for Hash keys).

+3
Aug 25 '08 at 7:59
source share



All Articles