在 C 中将 uint_8* 转换为任何类型,例如 "double" 或结构?

Convert uint_8* to any type, say "double" or a struct, in C?

在C语言中,我有一段程序是这样的

void foo(A a);

这里,类型A是已知的。它可以是任何类型,int、指针或结构,或任何用户编写的类型。

现在我有一个指针指向的数据,比如说 uint8_t* data 大小 n 如何将 data 转换为 A 类型的 a

我正在使用模糊测试后端从类型 uint8_t* 和大小 n 的随机数据中测试 foo。

假设您从流中读取字节 (uint8_t) 并希望将数据传递给您的函数 foo.

要遵循的步骤:

  • 您确定读取了数据类型 A 的序列化信息吗?
  • 您确定至少读取了 sizeof(A) 个字节吗?
  • 你确定你的类型 A 是(一般)可序列化的吗? (例如,如果 A 包含指向另一个对象的指针怎么办)

然后

foo((A) data); // <- remember: A is just a placeholder, but data is a pointer to uint8_t

Convert uint8_t* to any type in C?

无法用 C 语言进行通用操作。 C语言没有reflection,没有它就谈不上“任何类型”。在不知道“任何类型”对象表示形式并且不知道用于在 uint8_t 对象的指针 to/array 中对该对象进行编码的序列化方法的情况下,通常无法自动猜测转换函数。

您可以解释 uint8_t* 指向的字节集。使用指针别名将导致 strict alias violation and access may not be aligned 并可能最终导致未定义的行为。您也可以使用 memcpy(这很可能是您实际想要做的):

void foo(A a, size_t arrsize, uint8_t arr[arrsize]) {
    assert(arrsize >= sizeof(A)); // do some rudimentary safety checks
    memcpy(&a, arr, sizeof(A));
    // use a
    printf("%lf", a.some_member);
}

或使用 union 进行类型双关,但这可能会导致 trap representation and may cause program to perform a trap,但最终你会没事的。

实际将值数组转换为目标类型的唯一正确方法是实际编写deserialization/conversion函数。该算法将取决于 A 类型的对象表示以及源类型的格式和编码(json?yaml?“原始”(?)字节大端?小端?MSB? LSB? 等..).

请注意,uint8_t 表示一个正好占用 8 个字节的数字,范围为 0 到 255。在 C 中表示“字节”使用 unsigned char 类型。 unsigned char特别提到对齐要求最小,sizeof等于1可以alias any object with a char* pointer.