一、函数原型:
这函数主要就是向binder_io结构体里面写入一个string16的字符串。
/**
* 向 binder_io 结构体中写入一个 UTF-16 格式的字符串
* binder_io 结构体的指针 bio
* const char* 类型的字符串 _str
* */
void bio_put_string16_x(struct binder_io *bio, const char *_str)
{
unsigned char *str = (unsigned char*) _str;
size_t len;
uint16_t *ptr;
// 如果字符串为null,则向 bio 中写入 0xffffffff 表示空字符串,然后返回
if (!str) {
bio_put_uint32(bio, 0xffffffff);
return;
}
// 计算输入字符串的长度
len = strlen(_str);
// 检查字符串长度是否超出了定义的最大长度
if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
bio_put_uint32(bio, 0xffffffff);
return;
}
/* Note: The payload will carry 32bit size instead of size_t */
// 向 bio 结构体中写入字符串长度,使用 bio_put_uint32 函数将长度作为一个 32 位整数写入
bio_put_uint32(bio, len);
// 在 bio 结构体中分配足够空间来存储 UTF-16 格式的字符串,长度为 (len + 1) 个 uint16_t 字符
ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
if (!ptr)
return;
while (*str)
*ptr++ = *str++;
*ptr++ = 0;
}
1、科普小课堂:
有点啰嗦,主要是防止对c语言不熟悉的同学没注意到这个知识点,高手跳过!!
1)uint32_t和size_t:
注意看上面bio_put_uint32的注释:
/* Note: The payload will carry 32bit size instead of size_t */
为什么要强调uint32_t呢?那是因为:
size_t 的大小可能会根据不同的编译器、操作系统和硬件架构而有所不同,因此,转为uint32_t,保证可移植性 在32位系统上,size_t 通常是4字节(32位),而在64位系统上,size_t 通常是8字节(64位)
2)bio_alloc大小:
看下面这句代码,为什么分配大小是len+1,而不是len呢?
len+1是因为,c语言的字符串,最后面需要一个空字符 ('\0')
二、uint16_t ptr和char ptr:
uint16_t *ptr 和 char *ptr 在 C 语言中代表不同的数据类型和用途:
-
uint16_t *ptr:uint16_t是 C 语言标准中定义的一个无符号 16 位整数类型,通常用于存储 Unicode 字符或者处理 16 位数据。uint16_t *ptr声明了一个指向uint16_t类型数据的指针。这种指针通常用于处理 16 位数据,例如在处理 UTF-16 编码的字符串时会使用这种类型。
-
char *ptr:char是 C 语言中表示字符的数据类型,通常用于存储 ASCII 字符或者字节数据。char *ptr声明了一个指向char类型数据的指针。这种指针通常用于处理字符数据或字节数据,例如在处理字符串时经常会使用这种类型。
主要区别在于数据类型的不同:uint16_t 是一个 16 位整数类型,而 char 是一个字符类型。因此,根据所处理的数据的不同,选择合适的指针类型很重要。如果处理的是 16 位数据,如 UTF-16 编码的字符串,那么使用 uint16_t *ptr 更合适;而如果处理的是字符数据或字节数据,通常会使用 char *ptr。
在 C 语言中,指针的类型决定了指针所指向的数据类型,因此选择正确的指针类型能够更好地反映所处理数据的实际类型,避免数据类型转换或错误处理。
三、举例说明:
让我们通过一个具体的例子来说明 uint16_t *ptr 和 char *ptr 之间的区别。假设我们有一个 UTF-16 编码的字符串,我们将看到如何使用这两种指针类型来处理这个字符串。
假设我们有一个 UTF-16 编码的字符串 "Hello",其内部存储形式为 uint16_t 类型的数据。现在我们来看看如何使用 uint16_t *ptr 和 char *ptr 来处理这个字符串:
#include <stdio.h>
#include <stdint.h>
int main() {
// UTF-16 encoded string "Hello" (H: 0x0048, e: 0x0065, l: 0x006C, o: 0x006F, null termination: 0x0000)
uint16_t utf16_string[] = {0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x0000};
// Using uint16_t pointer to access UTF-16 encoded string
uint16_t *ptr_uint16 = utf16_string;
while (*ptr_uint16 != 0x0000) {
printf("%c", (char)(*ptr_uint16)); // Convert uint16_t to char for printing
ptr_uint16++;
}
printf("\n");
// Using char pointer to access UTF-16 encoded string byte by byte
char *ptr_char = (char *)utf16_string;
while (*ptr_char != 0x00 || *(ptr_char + 1) != 0x00) {
printf("%c", *ptr_char);
ptr_char += 2; // Move pointer by 2 bytes to access next UTF-16 character
}
printf("\n");
return 0;
}
在上面的例子中,我们首先定义了一个 UTF-16 编码的字符串 utf16_string,然后展示了如何使用 uint16_t *ptr 和 char *ptr 来访问这个字符串。
- 使用
uint16_t *ptr:我们通过逐个读取uint16_t类型的数据来访问 UTF-16 编码的字符串,然后将其转换为char类型来打印字符。 - 使用
char *ptr:我们将uint16_t类型的数据强制转换为char类型,以便以字节为单位来访问 UTF-16 编码的字符串。在这种情况下,我们需要注意跨越每个 UTF-16 字符的两个字节。
四、为什么要使用uint16_t指针?
选择使用 uint16_t *ptr 还是 char *ptr 取决于所处理的数据类型和操作粒度。如果处理的是 16 位数据或 UTF-16 编码的字符串,uint16_t *ptr 更为合适;而如果处理的是字节数据或者单字节字符,char *ptr 则更为适合。说白了还是编码方式决定的。