C - 内存布尔值以无效 *



我只是创建了一个测试函数,我必须在 void * 中传递布尔值,以便我可以在其他函数中解析它并使用它。

但是我被困住了,无法知道我应该如何在 void * 中对布尔值进行记忆。

但是当我在另一个函数中解析它时,我总是得到值 true。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct {
int a;
uint8_t var_data[];
} s;
void parse(s * dummy)
{
void *var_data = dummy->var_data;

uint8_t *len;
char type[128];
bool *leaf;
for(int i = 0; i < dummy->a; i++)
{
len = (uint8_t *)var_data;
var_data += 1;
memcpy(type, var_data, *len);
type[*len] = '';
var_data += *len;
leaf = (bool *)var_data;
var_data += 1;

printf("%sn", type);
printf("leaf: %snn", leaf ? "true" : "false");
}
}
int main() 
{
// Write C code here
char val[] = "dummy value";
uint8_t len = strlen(val);
bool v = false;
int b = 2;
int sz = sizeof(s) + b * (sizeof(bool) + len + 1);
s * dummy = (s *) malloc(sz);
dummy->a = b;
void *var = dummy->var_data;
for(int i = 0; i < dummy->a; i++){
memcpy(var, &len, 1);
var += 1;
memcpy(var, val, len);
var += len;
memcpy(var, &v, sizeof(bool));
var += sizeof(bool);
}
parse(dummy);
return 0;
}

身体可以帮助我解决这个问题。

var_data未初始化。您应该使用malloc分配var_data,并将leaf中的数据复制到其中:

void *var_data = malloc(sizeof(bool));
bool leaf = false;
memcpy(var_data, &leaf, sizeof(bool));

你可以像这样将其转换为bool *

bool *leaf;
leaf = (bool *) var_data;

此外,还可以递增指针var_data。所以var_data现在指向不同的内存位置。

您没有取消引用此行中的leaf

printf("leaf: %snn", leaf ? "true" : "false");

由于leaf是一个非零指针,因此它将始终计算为 C 中的true。您想改为打印*leaf

printf("leaf: %snn", *leaf ? "true" : "false");

其他一些杂项评论:

  1. void*算术(即var_data += 1)在C语言中是非法的,尽管gcc不会抱怨。使用char*,因为这是应该用于序列化的类型。

  2. 正如其他答案中提到的,像您现在所做的那样使用指针可能会导致微妙的错误。如果您的指针指向某个地址,并且您想要取消引用它(读取存储在那里的值),最好早点执行此操作,而不是同时冒着此位置被其他代码更改的风险。

    因此,只需将数据从char*数组复制到目标结构(或像uint8_t这样的基元)中,然后推进指针。

  3. 技术上讲,允许在C中投射指针的唯一方法是将它们特定的指针(如something*)投射到char*,以便检查它们的内容。您也可以隐式强制转换 from 和 tovoid*,但前提是您没有为指针设置别名(尝试修改基础类型)。其他方向的任何强制转换都违反了严格的混叠,因此您应该尝试改用memcpy。它可能看起来更丑陋,但编译器无论如何都会优化它(自己看),你会免受混叠的恐怖。

  4. 一个很好的习惯是让它尽可能利用常量正确性,它可以帮助编译器警告你,如果你做错了什么。如果您的函数正在解析数组,则参数应const char*

  5. 最后,如果您的目标是序列化和反序列化结构,也许您应该研究协议缓冲区或一些类似的序列化框架。它快速,高效,便携,最重要的是,已经编写好了。

所以,像这样:

typedef struct {
int len;  
char * var_data;
} example;
// note the const keyword - this means this function is
// not going to change the struct, only read it
void parse(const example * dummy)
{
// again, pointer to const char
const char * var_data = dummy->var_data;

// move all variables to the innermost scope
for (int i = 0; i < dummy->len; i++)
{
uint8_t len = 0;
memcpy(&len, var_data, sizeof(len));
var_data++;
...
}
}

最新更新