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

时间:2015-03-21 06:14:11

标签: c json parsing

我试图在这种情况下理解指针转换。

# 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,..从这里我&#39我输了。我真的不明白这个目的。

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

由于

3 个答案:

答案 0 :(得分:2)

_json_value::values是一个指向json_object_entry数组开头(或进入)的指针。代码将其值调整几个字节,例如为了在实际数据之前跳过标题等。由于指针是键入的,因此只能在sizeof(_json_object_entry)的常量中更改其值,但显然偏移量可以具有任何值,具体取决于某些string_length。所以指针的地址被占用,转换为char指针的地址(char指针可以以1为增量进行更改),取消引用,因此结果是一个指向char的指针,它位于与真实{{1}相同的位置},然后分配给。

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

答案 1 :(得分:1)

此处作者(有罪......)

在第一次传递中,values尚未分配,因此解析器通过使用相同的字段来存储当前需要的内存量(长度)时作弊。它实际上是在第二次传递中分配的。

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

json_char进行投射,以便我们将char的倍数添加到长度,而不是json_object_entry的倍数。

有点(......好吧,不止一点......)肮脏的黑客重新使用这样的字段,但它是为了保存向json_value添加另一个字段或使用联盟(C89联盟不能匿名,所以它会使json_value的结构有点怪异。)

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

答案 2 :(得分:0)

    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确实是指向values数组的第一个元素的指针。它指向指向json_char的指针,然后是高级string_length + 1个字符。最终结果是top-> u.object.values现在指向(string_length + 1)json_chars,比以前更早。