代码之家  ›  专栏  ›  技术社区  ›  nevan king

编译器是否优化了字符串格式?

  •  4
  • nevan king  · 技术社区  · 15 年前

    我试图回答另一个关于==运算符的问题,并创建了以下代码:

    NSString *aString = @"Hello";
    NSString *bString = aString;
    NSString *cString = @"Hello";
    
    if (aString == bString)
        NSLog(@"CHECK 1");
    
    if (bString == cString)
        NSLog(@"CHECK 2");
    
    if ([aString isEqual:bString])
        NSLog(@"CHECK 3");
    
    if ([aString isEqual:cString])
        NSLog(@"CHECK 4");
    
    NSLog(@"%i", aString);
    NSLog(@"%i", bString);
    NSLog(@"%i", cString);
    

    但对结果感到惊讶:

    Equal[6599:10b] CHECK 1
    Equal[6599:10b] CHECK 2
    Equal[6599:10b] CHECK 3
    Equal[6599:10b] CHECK 4
    Equal[6599:10b] 8240
    Equal[6599:10b] 8240
    Equal[6599:10b] 8240
    

    这里有编译器的诡计吗?

    4 回复  |  直到 15 年前
        1
  •  6
  •   Community CDub    8 年前

    显然,至少在一个编译单元中,正在进行字符串统一。我建议你进行一次简短的旅行 man gcc 在此期间,您将访问“string”的所有用法。您将发现一些与文字直接相关的选项 NSString S和他们的免费桥接同行, CFString S:

    • -fconstant-string-class = 类名 设置用于实例化的类的名称 @"..." 文字。它默认为 NSConstantString 除非使用GNU运行时。(如果你不知道自己是不是,你就不是。)
    • -fconstant-cfstrings 允许使用内置创建 CFSK 当你写作的时候 CFSTR(...) .

    您可以使用 -fwritable-strings 尽管此选项已弃用。我想不出一个能阻止 非字符串 目标C文件中的文本。(有人想和帕斯卡字符串文字交谈吗?)

    你看 -fconstant字符串 发挥作用 CFString.h 的定义 CFSTR() 用于创建的宏 CFSK 文字:

        #ifdef __CONSTANT_CFSTRINGS__
        #define CFSTR(cStr)  ((CFStringRef) __builtin___CFStringMakeConstantString ("" cStr ""))
        #else
        #define CFSTR(cStr)  __CFStringMakeConstantString("" cStr "")
        #endif
    

    如果您查看非内置的实现 __CFStringMakeConstantString() 在里面 CFString.c ,您将看到函数确实使用非常大的 CFMutableDictionary :

        if ((result = (CFStringRef)CFDictionaryGetValue(constantStringTable, cStr))) {
            __CFSpinUnlock(&_CFSTRLock);
        }
        // . . .
        return result;
    

    另见对问题的回答, "What's the difference between a string constant and a string literal?"

        2
  •  4
  •   user57368    15 年前

    nsstring被定义为一个不可变的类型,因此每当编译器通过组合相同的字符串来优化事物时,它就应该这样做。正如您的代码所演示的,gcc显然会针对简单的情况执行这种优化。

        3
  •  2
  •   chollida    15 年前

    对于Ctring和Actring,C、C++和Objic C编译器可以在一个以上的位置声明一个编译时字符串对象。

        4
  •  0
  •   stefanB    15 年前

    也许是简单的写上拷贝优化?因为所有3个字符串都指向同一个“字符集”,所以在修改其中一个字符串之前,不需要创建单独的副本。

    可能字符存储在内存的静态部分(带代码),nsstrings*指向内存的该部分。一旦尝试修改其中一个字符串,它将在其他地方创建新的字符串(堆),然后引用该内存。