了解 C 中结构类型的指针转​​换

Understanding pointer casting on struct type in C

我正在尝试理解这种情况下的指针转换。

# https://github.com/udp/json-parser/blob/master/json.c#L408

#define json_char char
typedef struct _json_object_entry
{
   json_char * name;
   unsigned int name_length;

   struct _json_value * value;

} json_object_entry;
typedef struct _json_value
{
struct
  {
     unsigned int length;

     json_object_entry * values;

     #if defined(__cplusplus) && __cplusplus >= 201103L
     decltype(values) begin () const
     {  return values;
     }
     decltype(values) end () const
     {  return values + length;
     }
     #endif

  } object;
}
(*(json_char **) &top->u.object.values) += string_length + 1;

根据我所见,top->u.object.values 具有值的第一个元素的地址(类型:json_object_entry),然后我们得到值的地址,将其转换为 char,..从这里我迷路了。我真的不明白这样做的目的。

// 注意:对于那些想知道这是什么的人来说,这是两遍解析器。

谢谢

_json_value::values 是指向(或进入)json_object_entry 数组开头的指针。该代码将其值调整了几个字节,例如,为了在实际数据之前跳过 header 等。因为指针是类型化的,所以可以在不强制转换的情况下仅更改其 sizeof(_json_object_entry) 数量中的值,但显然偏移量可以具有任何值,具体取决于某些 string_length。所以指针的地址被获取,转换为一个 char 指针的地址(一个 char 指针可以以 1 为增量改变),取消引用所以结果是一个指向 char 的指针,与真正的 u.object.values,然后赋值给.

如果架构要求结构的最小对齐(可能取决于它们的第一个元素,这里是指针)并且字符串长度可以有一个值,那么这样的代码可能会在 运行 时中断不是该对齐的倍数。这将使代码成为 UB。如果保留对齐方式,我不确定代码名义上是否是 UB。

    json_object_entry * values;
...
}

(*(json_char **) &top->u.object.values) += string_length + 1;

忘记类型正确性,您可以折叠 & 和 *:

((json_char **) top->u.object.values) += string_length + 1;

top->u.object.values 确实是指向值数组第一个元素的指针。它被类型转换为指向 json_char 的指针,然后前进 string_length + 1 个字符。最终结果是 top->u.object.values 现在比以前指向 (string_length + 1) json_chars。

这里是作者(被指控有罪...)

在第一遍中,values 尚未分配,因此解析器通过使用相同的字段来存储实际分配时所需的内存量(长度)来作弊第二关

if (state.first_pass)
    (*(json_char **) &top->u.object.values) += string_length + 1;

转换为 json_char 是为了让我们在长度上添加 char 的倍数,而不是 json_object_entry.

的倍数

像那样重新使用该字段有点(...好吧,不止...)一个肮脏的 hack,但它是为了节省向 json_value 添加另一个字段或使用联合(C89 联合不能匿名,所以它会使 json_value 的结构有点奇怪)。

这里没有 UB,因为此时我们实际上并没有将 values 用作结构数组,只是颠覆了类型系统并将其用作整数。