有人可以解释编译器存储字符串常量的位置和方式,以及运行时如何访问它们?
答案 0 :(得分:11)
首先是强制性的:你应该不关心编译器是如何做到的;基于编译器如何执行此操作的任何操作都是对某些无法保证的内容的危险依赖,并且可能会根据编译器的优化方式进行更改。不要基于此编写代码。真。好的,我们已经解决了这个问题。
假设你有这样的代码:
NSString *something = @"I'm a constant";
编译器将生成:
.section __TEXT,__cstring,cstring_literals
l_.str: ## @.str
.asciz "I'm a constant"
如您所见,它与您的代码一起存储在__TEXT部分中,作为cstring文字。在__DATA中,它将像这样存储常量CFString:
.section __DATA,__cfstring
.align 4 ## @_unnamed_cfstring_
L__unnamed_cfstring_:
.quad ___CFConstantStringClassReference
.long 1992 ## 0x7c8
.space 4
.quad l_.str
.quad 14 ## 0xe
首先,它存储CFType
(CFConstantStringClassReference
)。然后是关于字符串的内部信息(它是不可变的,如何解除分配,是unicode等),指向cstring的指针和长度(14)。如果您想了解结构的详细信息,请从opensource.apple.com下载CF源并查看CFString.c
。它很好地解释了整个“内部信息”领域。 (从Snow Leopard中取出它们; Apple不会将它们作为iOS的一部分发布,但它们是相同的。)
第二个常量字符串看起来像这样,只是为了演示如何为汇编程序完成符号命名。
.section __TEXT,__cstring,cstring_literals
l_.str2: ## @.str2
.asciz "%@"
.section __DATA,__cfstring
.align 4 ## @_unnamed_cfstring_3
L__unnamed_cfstring_3:
.quad ___CFConstantStringClassReference
.long 1992 ## 0x7c8
.space 4
.quad l_.str2
.quad 2 ## 0x2
如果你想更好地处理这个问题,只需要让Xcode生成一个简单文件的程序集,看看它的作用。哦,当然你永远不应该使用这些信息,因为gcc
可能随时改变。但是深入挖掘它是件好事。
答案 1 :(得分:1)
您应该创建一个像
这样的头文件// Constants.h
extern NSString * const MyFirstConstant;
extern NSString * const MySecondConstant;
//etc.
您可以在使用常量的每个文件中或在项目的预编译头中包含此文件。
您可以在.m文件中定义这些常量,例如
// Constants.m
NSString * const MyFirstConstant = @"FirstConstant";
NSString * const MySecondConstant = @"SecondConstant";
应将Constants.m添加到您的应用程序/框架的目标中,以便将其链接到最终产品。
使用字符串常量而不是#define
'常量的优点是可以使用指针比较(stringInstance == MyFirstConstant
)测试相等性,这比字符串比较([stringInstance isEqualToString:MyFirstConstant]
)快得多