NDK-以十六进制字符串的形式打印char[]数组到logcat
NDK-以十六进制字符串的形式打印char[]数组到logcat
1. 在Java中打印
public static String convertByteArr2String(byte[] bArr) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < bArr.length; i++) {
builder.append(String.format(Locale.getDefault(), "%02x", bArr[i]).toUpperCase()).append(" ");
}
return builder.toString();
}
2. 在C语言中打印
在 Android NDK 开发中,需要使用 __android_log_print
函数来输出日志信息。这个函数是 Android NDK 的日志系统的一部分,类似于 Java 中的 Log
类。要使用它,你需要包含头文件 <android/log.h>
。
以下是一个示例,展示如何使用 __android_log_print
在 NDK 中打印一个 char
数组的十六进制表示:
#include <android/log.h>
#include <stdio.h>
#define LOG_TAG "MyTag"
void printHex(const char* arr, int length) {
char buffer[3 * length + 1]; // 每个字节最多占用3个字符(两个十六进制字符和一个空格)加上终止字符
char *ptr = buffer;
for (int i = 0; i < length; i++) {
ptr += sprintf(ptr, "%02X ", arr[i]);
}
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Hex string: %s", buffer);
}
int main() {
char arr[] = {0x1a, 0x2b, 0x3c, 0x4d}; // 示例数组
int length = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
printHex(arr, length);
return 0;
}
这个代码定义了一个 printHex
函数,它接受一个 char
数组和它的长度,然后构建一个包含数组十六进制表示的字符串。sprintf
函数用于将每个数组元素转换为十六进制格式。最后,使用 __android_log_print
将构建好的十六进制字符串输出到日志中。
要注意的是,你需要在你的 NDK 项目中正确配置 Android.mk
和 Application.mk
文件,以便包含和链接 Android 的日志库。如果使用的是CMake,需要在 target_link_libraries
中添加日志库的引用:
target_link_libraries(
my-jni-lib
log # 必须
)
3. 关于sprintf()函数
3.1 是否需要在输出的字符串末尾添加 '\0'结束符?
在上面的例子中:
for (int i = 0; i < length; i++) {
ptr += sprintf(ptr, "%02X ", arr[i]);
}
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Hex string: %s", buffer);
在格式化字符串后,直接使用 __android_log_print()
函数对log进行了输出,那是否需要在buffer
的字符串末尾添加 \0
结束符呢?我们知道C语言字符串的末尾是需要以\0
结束的,用于标识字符串结束。
答案是不需要的。原因在于:
在上述代码中,使用 sprintf
函数时,每次调用都会自动在生成的字符串末尾添加一个空字符(\0
),作为字符串的终止符。因此,在迭代完整个数组后,buffer
数组的最后一个元素已经是由 sprintf
在其最后一次调用时自动添加的空字符。
这意味着在循环结束后,你不需要显式地将 buffer
数组的最后一个字节置为 0,因为 sprintf
已经为你处理了这个问题。每次 sprintf
被调用时,它都会在写入数据的末尾添加一个 \0
字符,确保了字符串是正确终止的。
根据 C 语言的标准,
sprintf
函数在向目标字符串写入内容后,总是会在末尾自动添加一个空字符('\0'
),作为字符串的结束标志。这是 C 语言中所有标准字符串函数的通用行为:字符串总是以空字符结束。当你使用
sprintf
或类似函数(如snprintf
、strcpy
、strcat
等)时,它们会在完成字符串操作后,在字符串的末尾添加一个'\0'
。这确保了字符串是正确终止的,使其成为一个合法的 C 字符串。因此,在使用这些函数处理字符串时,你需要确保有足够的空间来容纳所有字符,包括终止的空字符。
3.2 p+= sprintf(), 这里加的值是几?指针每次偏移多少?
在上述例子中的 ptr += sprintf(ptr, "%02x ", arr[i]);
表达式里,sprintf
函数的返回值是它写入 ptr
指向的字符串的字符数(注意不包括终止的空字符 \0
)。对于格式 %02x
:
%02x
会产生两个字符,代表一个字节的十六进制表示。- 空格
' '
会产生一个额外的字符。
因此,对于每个数组元素,sprintf
将产生 3 个字符(两个十六进制数字和一个空格)。所以,ptr
每次会向前移动 3 个字符的位置。
假设 arr[i]
是 0x1A
,那么 sprintf(ptr, "%02x ", arr[i]);
会在 ptr
指向的位置写入 "1a "
,然后返回 3,表示写入了 3 个字符。之后,ptr
就会向前移动 3 个位置,准备下一次的写入。
<完>