当格式包含非 ASCII 字符时 sprintf 不工作
sprintf not working when format contains non-ASCII characters
以下对 sprintf
的调用在为 i386 arch 编译时失败。使用 Android NDK。我试过用 GCC 和 clang 编译,结果是一样的。我正在使用 android-ndk-r10e
(GCC 将 APP_STL 设置为 gnustl_shared
,clang 设置为 c++_shared
)。它的工作原理是 (I?) 在为具有相同配置的 ARM 编译时,此外当我用 GCC 5.2 为 i386 Linux 编译时。
int n = sprintf(buf, "\xc0%s", "test"); // n == 0, strlen(buf) == 0
调用后,buf
为空,而不是包含预期的字符序列“\xc0test”。 sprintf
似乎忽略了第一个非 ASCII 字符之后的所有内容。以下代码将 "test" 写入 buf
,省略最后一个字节:
sprintf(buf, "%s\xc0", "test"); // strlen(buf) == 4
另一方面,这工作正常:
sprintf(buf, "%s", "test\xc0"); // strlen(buf) == 5
我很困惑。
这是已知的 Android 问题。问题在于 Android libc 实现(Bionic),它在符合标准方面相当不完整。特别是,Bionic stdio 实现不能正确支持非 ASCII 字符。
这个简单的测试在由 Android NDK r10e:
构建时打印 strlen(buf)=4
#include <stdio.h>
#include <string.h>
int main()
{
char buf[256];
sprintf(buf, "%s\xc0", "test");
printf("strlen(buf)=%d\n", strlen(buf));
return 0;
}
解决方案:使用 CrystaX NDK - Google 的 Android NDK 的替代分支,其中的问题已得到修复。如果由 CrystaX NDK 10.3.1 构建,上面的示例可以正常工作:
strlen(buf)=5
以下对 sprintf
的调用在为 i386 arch 编译时失败。使用 Android NDK。我试过用 GCC 和 clang 编译,结果是一样的。我正在使用 android-ndk-r10e
(GCC 将 APP_STL 设置为 gnustl_shared
,clang 设置为 c++_shared
)。它的工作原理是 (I?) 在为具有相同配置的 ARM 编译时,此外当我用 GCC 5.2 为 i386 Linux 编译时。
int n = sprintf(buf, "\xc0%s", "test"); // n == 0, strlen(buf) == 0
调用后,buf
为空,而不是包含预期的字符序列“\xc0test”。 sprintf
似乎忽略了第一个非 ASCII 字符之后的所有内容。以下代码将 "test" 写入 buf
,省略最后一个字节:
sprintf(buf, "%s\xc0", "test"); // strlen(buf) == 4
另一方面,这工作正常:
sprintf(buf, "%s", "test\xc0"); // strlen(buf) == 5
我很困惑。
这是已知的 Android 问题。问题在于 Android libc 实现(Bionic),它在符合标准方面相当不完整。特别是,Bionic stdio 实现不能正确支持非 ASCII 字符。
这个简单的测试在由 Android NDK r10e:
构建时打印strlen(buf)=4
#include <stdio.h>
#include <string.h>
int main()
{
char buf[256];
sprintf(buf, "%s\xc0", "test");
printf("strlen(buf)=%d\n", strlen(buf));
return 0;
}
解决方案:使用 CrystaX NDK - Google 的 Android NDK 的替代分支,其中的问题已得到修复。如果由 CrystaX NDK 10.3.1 构建,上面的示例可以正常工作:
strlen(buf)=5