15 年間 C コードを書いてきましたが、このようなコードは見たことがなく、どのように機能するのかわかりません。これは、何らかの方法で複数行のコードが整数値に解決される C99 コードを中心にしています。これは libplist から来ています。具体的にはhereです。394 行目から始まります。ここでは、構造体の uint64_t メンバーに、マクロ UINT_TO_HOST の結果が割り当てられています。
data->intval = UINT_TO_HOST(&data->intval, size);
UINT_TO_HOST は、符号なし整数へのポインターと、整数のバイト単位のサイズを受け取るマクロです。マクロは、異なる uint サイズの一連のポインターへの共用体を定義し、マクロに渡された uint ポインターにアドレスを設定します。次に、uint を別のマクロと適切にバイト スワップするために、メモリ内で uint の位置合わせを行います。UINT_TO_HOST は 172 行で定義されています
#define UINT_TO_HOST(x, n) \
({ \
union plist_uint_ptr __up; \
__up.src = x; \
(n == 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
(n == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
(n == 3 ? uint24_from_be( __up ) : \
(n == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
*__up.u8ptr )))); \
})
get unaligned は、構造体と gcc 属性がパックされたトリックを実行します。これは、型に基づいてメモリ内で整列されたポインター値を返します。
#define get_unaligned(ptr) \
({ \
struct __attribute__((packed)) { \
typeof(*(ptr)) __v; \
} *__p = (void *) (ptr); \
__p->__v; \
})
be64toh は、その場でマスキングとシフトを行うだけです。
#define be64toh(x) ((((x) & 0xFF00000000000000ull) >> 56) \
| (((x) & 0x00FF000000000000ull) >> 40) \
| (((x) & 0x0000FF0000000000ull) >> 24) \
| (((x) & 0x000000FF00000000ull) >> 8) \
| (((x) & 0x00000000FF000000ull) << 8) \
| (((x) & 0x0000000000FF0000ull) << 24) \
| (((x) & 0x000000000000FF00ull) << 40) \
| (((x) & 0x00000000000000FFull) << 56))
UINT_TO_HOST は基本的に一連の中括弧 {} 内の 3 行のコードに解決されるため、問題は UINT_TO_HOST が実際に data->intval に値を返す方法です。同じことが get_unaligned 内で発生しているように見えます。おそらく最後のステートメント
__p->_v;
返されるものです。この機能は何と呼ばれていますか?この「機能」に関するドキュメントを参照できる人はいますか?