简体   繁体   English

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

[英]Understanding pointer casting on struct type in C

I'm trying to understanding the pointer casting in this case. 我正在尝试了解这种情况下的指针转换。

# 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;

Due to what I see top->u.object.values has the address of the first element of values ( type : json_object_entry ), and then we get the address of values, casting it to char, .. And from here I'm lost. 由于我看到top->u.object.values具有值的第一个元素的地址(类型:json_object_entry),然后我们获得值的地址,并将其转换为char,..从这里开始丢失。 I don't really understand the purpose of this. 我真的不明白这个目的。

// Notes : This is two pass parser for those who wonders what is this. //注意:对于那些想知道这是什么的人,这是两遍解析器。

Thanks 谢谢

_json_value::values is a pointer to the beginning of (or into) an array of json_object_entry s. _json_value::values是指向json_object_entry数组开头(或指向数组json_object_entry )的json_object_entry The code adjusts its value by a few bytes, eg in order to skip a header or such before the actual data. 该代码将其值调整了几个字节,例如,以便在实际数据之前跳过标头等。 Because the pointer is typed one can without casting only change its value in quants of sizeof(_json_object_entry) , but apparently the offset can have any value, depending on some string_length . 因为键入了指针,所以无需强制转换就只能以sizeof(_json_object_entry)数量更改其值,但是显然偏移量可以具有任何值,具体取决于某些string_length So the address of the pointer is taken, cast to the address of a char pointer (a char pointer can be changed in 1 increments), dereferenced so the result is a pointer to char residing at the same place as the real u.object.values , and then assigned to. 因此,将指针的地址转换为char指针的地址(char指针可以1的增量进行更改),并取消引用,因此结果是指向char的指针与实际u.object.values位于同一位置u.object.values ,然后分配给。

One should add that such code may break at run time if the architecture demands a minimal alignment for structures (possibly depending on their first element, here a pointer) and the string length can have a value which is not a multiple of that alignment. 应该补充的是,如果体系结构要求结构的最小对齐(可能取决于它们的第一个元素,这里是一个指针),并且字符串长度的值不能是该对齐的倍数,则此类代码可能在运行时中断。 That would make the code UB. 这将使代码UB。 I'm not exactly sure whether the code is nominally UB if the alignment is preserved. 如果保留对齐方式,我不确定代码是否名义上属于UB。

Author here (guilty as charged...) 在这里作者(有罪...)

In the first pass, values hasn't yet been allocated, so the parser cheats by using the same field to store the amount of memory (length) that's going to be required when it's actually allocated in the second pass. 在第一遍中,尚未分配values ,因此解析器使用相同的字段作弊,以存储在第二遍中实际分配的内存量(长度)。

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

The cast to json_char is so that we add multiples of char to the length, rather than multiples of json_object_entry . json_charjson_char ,以便我们将char倍数增加到长度,而不是json_object_entry

It is a bit (...OK, more than a bit...) of a dirty hack re-using the field like that, but it was to save adding another field to json_value or using a union (C89 unions can't be anonymous, so it would have made the structure of json_value a bit weird). 这有点(...还可以,还有更多...),是像这样肮脏的hack重用了该字段,但是这样做是为了节省将另一个字段添加到json_value或使用联合(C89联合不能是匿名的,因此会使json_value的结构有些怪异)。

There's no UB here, because we're not actually using values as an array of structs at this point, just subverting the type system and using it as an integer. 这里没有UB,因为此时我们实际上并没有使用values作为结构数组,只是颠覆了类型系统并将其用作整数。

    json_object_entry * values;
...
}

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

forgetting type correctness, you can collapse the & and *: 忘记类型正确性,可以折叠&和*:

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

top->u.object.values is indeed the pointer to first element of values array. top-> u.object.values实际上是指向values数组第一个元素的指针。 It is typecasted to a pointer to a pointer to json_char, and then advanced string_length + 1 characters. 它被类型转换为一个指向json_char的指针,然后是高级string_length +1个字符。 The net result is that top->u.object.values now points (string_length + 1) json_chars ahead of what it used to. 最终结果是,top-> u.object.values现在指向(string_length +1)json_chars之前。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM