我第一次使用Apple的Unified Logging,并取得了一些成功。但是,我无法使用建议的%{timeval}.*P
自定义格式说明符。
我的第一次尝试是:
struct timeval some_time;
// ... populate `some_time`
os_log_info(OS_LOG_DEFAULT, "a thing happened at %{timeval}.*P", some_time);
但clang报告错误:field precision should have type 'int', but argument has type 'struct timeval'
。
我认为问题在于clang并不理解os_log
格式规则,如果我能解决如何让clang通过clang diagnostic push
等来抑制错误, 我会。看起来基础宏OS_LOG_CALL_WITH_FORMAT
似乎试图做到这一点,没有运气。
我是否滥用timeval
格式说明符?
这是Xcode 8.3.1,我还没有尝试过早期版本的Xcode。
答案 0 :(得分:1)
根据documentation,timeval
格式说明符是正确的。显然,从Xcode 8.3.2开始,Clang还没有意识到这些新的格式字符串。通过#clang diagnostic ignored "-Wformat"
停用它将是徒劳的尝试。
显然没有解决方案 - 同时避免使用这些新的花式格式说明符。具体来说,请避免使用以.*P
结尾的格式字符串。但是d
格式似乎有效。
答案 1 :(得分:1)
<强> TL; DR 强>
工作代码
os_log_info(OS_LOG_DEFAULT, "a thing happened at %{timeval}.16P", &some_time);
OR
os_log_info(OS_LOG_DEFAULT, "a thing happened at %{timeval}.*P", (int)sizeof(some_time), &some_time);
这里的问题是格式定义中的通配符(*)代表int。所以事实上%{timeval}。* P接受2个参数:int和指向timeval struct的指针。
不幸的是,这是非常糟糕的文档,甚至os_log使用的Apple Sample Code都没有这方面的例子。
到目前为止,查看示例的最佳方法是查看LLVM源代码中的测试。 format-strings-oslog.m
__builtin_os_log_format(buf, "%d", i);
__builtin_os_log_format(buf, "%P", p); // expected-warning {{using '%P' format specifier without precision}}
__builtin_os_log_format(buf, "%.10P", p);
__builtin_os_log_format(buf, "%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
__builtin_os_log_format(buf, "%.*P", i, p);
__builtin_os_log_format(buf, "%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}