C 格式字符串在 Android Lollipop 中被截断

C format strings get truncated in Android Lollipop

我有以下 C 代码行将 degrees/minutes/seconds 格式化为字符串。

g_strdup_printf("%d°%d'%d\" %c%c%d°%d'%d\" %c",
    lat_deg,lat_min,lat_sec,latc,sep,lng_deg,lng_min,lng_sec,lngc);

该代码是跨平台应用程序的一部分,该应用程序可在多个平台上运行,包括 Linux 和 Android。从 Android Lollipop 开始,字符串在一次度数处被截断。我得到的不是 42°43'44" N 45°46'47" E,而是 42。事实上 strlen 报告字符串长度为 2 个字符。

此代码在早期 Android 版本(至少 Gingerbread 到 KitKat)上运行完美。它也适用于 Linux,过去我在 Windows CE 和桌面 Windows.

上成功使用过它

Lollipop 上发生了什么,我该如何解决?

显然 Lollipop 在 C 格式字符串中存在扩展字符(任何超过 7 位的字符)问题:

当我用空格替换度数符号时,结果符合预期。当我用扩展 ANSI 集中的任何其他字符替换它们时,它们会被截断,就好像该字符是 [=12=] – 如果我使用适当的转义序列,如 \xb0\u00b0,也是如此。所以显然是扩展的 ANSI 字符给我们带来了麻烦。

当我做的时候

g_strdup_printf("42°43'44\" N 45°46'47\" E");

我得到了一个格式正确的字符串。所以很明显这个问题只影响字符串格式化例程,而不影响通用字符串的东西——这也解释了为什么静态字符串中的坐标会起作用。

在度数符号的格式字符串中添加占位符并将它们作为额外参数传递也无济于事——它们会显示为 mojibake 并导致渲染代码崩溃。

我最终完全绕过了字符串格式化例程并做了:

g_strjoin(NULL,
        g_strdup_printf("%d", lat_deg), "°",
        g_strdup_printf("%d", lat_min), "'",
        g_strdup_printf("%d", lat_sec), "\" ",
        g_strnfill(1, latc),
        g_strnfill(1, sep),
        g_strdup_printf("%d", lng_deg), "°",
        g_strdup_printf("%d", lng_min), "'",
        g_strdup_printf("%d", lng_sec), "\" ",
        g_strnfill(1, lngc),
        NULL);