打印Cstring(UTF-8)时NSLog()vs printf()

我注意到,如果我尝试使用格式说明符“%s”打印包含UTF-8string表示forms的字节数组, printf()会正确,但是NSLog()会将其乱码(即每个字节按照原样打印,例如“¥”打印为2个字符:“¬•”)。 这很好奇,因为我总是认为NSLog()只是printf() ,加上:

  1. 第一个参数('格式')是一个Objective-Cstring,而不是Cstring(因此是“@”)。
  2. 时间戳和应用程序名称预先。
  3. 换行符自动添加到最后。
  4. 打印Objective-C对象的能力(使用格式“%@”)。

我的代码:

 NSString* string; // (...fill string with unicode string...) const char* stringBytes = [string cStringUsingEncoding:NSUTF8Encoding]; NSUInteger stringByteLength = [string lengthOfBytesUsingEncoding:NSUTF8Encoding]; stringByteLength += 1; // add room for '\0' terminator char* buffer = calloc(sizeof(char), stringByteLength); memcpy(buffer, stringBytes, stringByteLength); NSLog(@"Buffer after copy: %s", buffer); // (renders ascii, no matter what) printf("Buffer after copy: %s\n", buffer); // (renders correctly, eg japanese text) 

不知何故,看起来printf()NSLog()更“聪明”。 有没有人知道底层原因,如果这个functionlogging在任何地方? (找不到)

NSLog()stringWithFormat:似乎期望在“系统编码”中的%s的string(例如我的电脑上的“Mac Roman”):

 NSString *string = @"¥"; NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(CFStringGetSystemEncoding()); const char* stringBytes = [string cStringUsingEncoding:enc]; NSString *log = [NSString stringWithFormat:@"%s", stringBytes]; NSLog(@"%@", log); // Output: ¥ 

当然,如果某些字符在系统编码中不可表示,这将会失败。 我找不到这种行为的官方文档,但是可以看到在stringWithFormat:NSLog()中使用%s不能可靠地使用任意的UTF-8string。

如果要检查包含UTF-8string的char缓冲区的内容,则可以使用任意字符(使用盒装expression式语法从UTF-8string创buildNSString ):

 NSLog(@"%@", @(utf8Buffer));