(Android NDK)包含非ASCII字符的字符串被截断

(Android NDK)包含非ASCII字符的字符串被截断,c,android-ndk,java-native-interface,C,Android Ndk,Java Native Interface,我正在尝试使用NDK和JNI将一个用C编写的程序移植到Android上,我遇到了一个荒谬的问题,这让我发疯 简而言之,如果我这么做 char str[1024]; sprintf(str, "Hellö, this is söme stränge letters."); char str[1024]; sprintf(str, "Hellö again. Here's a number: %d", 1); …strlen(str)按预期返回35。对吧? 但是如果我包括一个说明符,并且这样做

我正在尝试使用NDK和JNI将一个用C编写的程序移植到Android上,我遇到了一个荒谬的问题,这让我发疯

简而言之,如果我这么做

char str[1024];
sprintf(str, "Hellö, this is söme stränge letters.");
char str[1024];
sprintf(str, "Hellö again. Here's a number: %d", 1);
…strlen(str)按预期返回35。对吧?

但是如果我包括一个说明符,并且这样做

char str[1024];
sprintf(str, "Hellö, this is söme stränge letters.");
char str[1024];
sprintf(str, "Hellö again. Here's a number: %d", 1);
…strlen(str)返回4

你看到发生什么事了吗?如果我尝试格式化字符串中的非ASCII字符,NDK似乎无法(或不会?)接受它们

每当我在格式字符串中包含一个大于127的ASCII字符时,它就会被截断。好像它是空终止的

这是虫子吗?这是预期的行为吗

最后,我的问题是:我能做些什么来解决这个问题?

非常感谢。

Android 5.0的“预览版”在最终版本中解决了一些问题。有关更多信息,请参阅

如果您获得.o文件的十六进制转储(在Linux上使用例如
xxd
)并搜索字符串片段,您可以看到它在可执行文件中的编码方式。如果它是有效的UTF-8——当我使用桌面gcc编译'ö'时,我得到了
c3b6
,那么它应该可以工作。如果它使用其他编码,Android libc可能会因为无效而拒绝它


如果二进制文件中的字符串似乎不是UTF-8,请检查makefile中的
-fexec charset=

是否查看str的编码?它很可能是以非ASCII友好的方式编码的,比如UTF-8。@bruceg不,对不起,我没有。我该怎么做?“我该怎么做?”对
str
的内容进行十六进制转储(即,对于值为0的字节,打印“00”;对于值为255的字节,打印“FF”,等等)。@Michael谢谢,但在我继续对字符串进行编码之前,我必须先将其组装起来。现在,我甚至无法创建要编码的字符串,因为sprintf()拒绝这些字符。我用HxD查看它,如果我读对了,“ö”只是一个字节,它是十六进制的F6。我的makefile中也没有任何
-fexec charset=
。我正在使用ndk构建Windows。我的构建目标是android-22(5.1.1),我的手机是5.1.1。我无法让sprintf()接受这些字符…这就是拒绝的原因。您需要将字符的UTF-8编码表示形式放入字符串中。(作为实验,尝试显式添加它,例如,
“Hell\xc3\xb6”
)获取源文件的十六进制转储,以查看编辑器是否正在编写UTF-8或CP-1252——gcc可能不理解您的意图。如果无法将编辑器配置为编写UTF-8,则可能需要将
-finput charset=
指定给gcc,以匹配它实际使用的内容。FWIW,注意在bug报告中我链接了一些人的例子,他们发现替换
sprintf()
更容易。