構造体フィールドoffset計算
char・int・charの構造体は6バイトではなく12バイトになります。各メンバーのオフセット、その前のパディング、末尾のパディングを、コンパイラと同じ規則で表示します。ブラウザで無料で使えます。
- 無料
- ブラウザで動作
- 登録不要
- データは端末の外に出ません
無料で実行
CおよびC++コンパイラは、構造体の各メンバをその自然整列を尊重するバイトoffsetに配置し、構造体配列が整列したままになるよう型全体をパディングします。そのレイアウトこそがoffsetofマクロとsizeof演算子が報告する内容です。それでもABIや#pragma packをまたいで手計算すると、バイナリプロトコル・FFIバインディング・メモリダンプで静かな不整合が起きます。任意のpackはpacked構造体を、任意のabiはlongとポインタ幅のLP64・LLP64・ILP32を選びます。
コンパイラがメンバーを並べる仕組み
宣言順のメンバ列に対し、コンパイラは0から始まるバイトカーソルを保ちます。最後のメンバの後、構造体整列(全メンバの実効整列の最大)の倍数になるよう末尾パディングを入れることがあります。その最終サイズがsizeofの戻り値であり、記録された各アドレスが対応するメンバ名に対するoffsetofの戻り値です。
スカラーの自然整列はプラットフォームABIに従います。LP64ではcharは1バイトで整列1、shortは2、intは4、longとポインタは8、floatは4、doubleは8です。LLP64ではlongは4のままポインタは8、ILP32ではlongとポインタの両方を4とします。
自然レイアウトでcharの直後にintが来ると、intの前に3バイトのパディングが入りoffsetは1から4へ飛びます。その跳びを理解することがoffsetofツールの目的です。メモリダンプ・ワイヤ形式・生成バインディングは、サイズの雑な足し算ではなくコンパイラと一致しなければなりません。
活用例
FFIと複数ABIバインディング
同一メンバ一覧についてLP64・LLP64・ILP32レイアウトを生成または検証し、ネイティブバインディングを各データモデルに合わせます。
よくある質問
offsetofマクロと一致しますか?
選択したABIと任意のpackの下でスカラーメンバについてははい。offsetとsizeofは、自然またはpackedなスカラー構造体に対するコンパイラと同じ配置規則に従います。
packは何をしますか?
packは#pragma pack(n)をモデル化します。自然(非packed)レイアウトではpackを省略してください。
どのABIが使えますか?
lp64(既定: longとポインタ8バイト)、llp64(Windows 64ビット: long 4、ポインタ8)、ilp32(longとポインタ4)です。
C構造体の各メンバーのオフセットはどう求めますか?
宣言順にメンバーを並べて入力します。0から始まる位置を各メンバーの整列の倍数に切り上げ、その位置をオフセットとして記録し、メンバーのサイズ分だけ進めます。
sizeofがメンバーの合計より大きくなるのはなぜですか?
コンパイラがパディングを入れるためです。char・int・charでは、intの前に3バイト入ってオフセット4から始まり、末尾にも3バイト入って、合計12が構造体の整列4の倍数になります。
関連ツール
開発者向け — APIアクセス
このページの機能はすべてAPIからも利用できます。自社システムに組み込みたいチーム向けのセクションです。それ以外の方は上のツールをそのままお使いください。
エンドポイント
Bearerトークンで認証し、POST1回でタスクをキューに登録します。結果はWebhookまたは署名付きリンクで受け取れます。
お使いのスタックから呼び出す
curl -X POST https://api.kit.forhosting.com/dev/struct-field-offset \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"fields":[{"name":"a","type":"char"},{"name":"b","type":"int"},{"name":"c","type":"char"}]}'const res = await fetch("https://api.kit.forhosting.com/dev/struct-field-offset", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"fields": [
{
"name": "a",
"type": "char"
},
{
"name": "b",
"type": "int"
},
{
"name": "c",
"type": "char"
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/struct-field-offset",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"fields": [
{
"name": "a",
"type": "char"
},
{
"name": "b",
"type": "int"
},
{
"name": "c",
"type": "char"
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/struct-field-offset", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"fields":[{"name":"a","type":"char"},{"name":"b","type":"int"},{"name":"c","type":"char"}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"fields":[{"name":"a","type":"char"},{"name":"b","type":"int"},{"name":"c","type":"char"}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/struct-field-offset", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)リクエスト例
{
"fields": [
{
"name": "a",
"type": "char"
},
{
"name": "b",
"type": "int"
},
{
"name": "c",
"type": "char"
}
]
}レスポンス例
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.struct_field_offset",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}非同期APIです。task_idは即時に返ります。ポーリングは1秒あたり1リクエストまでです。
料金
単価はすべて公開しています。トークン換算や独自クレジットはありません。失敗したタスクは課金されません。
エラー
| HTTP | コード | 意味 |
|---|---|---|
401 | unauthorized | APIキーが無効か、指定されていません。Authorizationヘッダーを確認してください。 |
402 | insufficient_balance | 残高が不足しています。チャージ後に再度お試しください。 |
404 | unknown_type | 指定されたタスクタイプは存在しません。タイプ名を確認してください。 |
429 | rate_limited | リクエストが多すぎます。しばらく待ってから再度お試しください。 |
技術的な注記
本構造体フィールドoffset計算機は、既知のCスカラー型または明示的なsizeとalignmentを持つフィールドの順序付きリストを受け取り、コンパイラと同じ切り上げ規則を適用し、各フィールドのoffset・直前パディング・構造体の総サイズ・全体整列・末尾パディングを返します。無料のブラウザ経路と前払いAPIは同一の純解析モジュールを共有するため、演習キーと本番オラクルが食い違うことはありません。検証失敗はinvalid_inputとなり課金されません。
Cがフィールドを置く仕組み: 整列・パディング・sizeof
フィールドを置く前に、そのフィールドの実効整列の倍数へカーソルを切り上げ、そのアドレスをフィールドoffsetとして記録し、フィールドsize分だけカーソルを進めます。切り上げで飛ばしたバイトはメンバ直前のパディングとなり、フィールド自身の領域には入りません。本計算機はこれらの表を内蔵しているため、フィールド一覧を書き直さずにABIを切り替えられます。隣接する2フィールドにパディングが不要ならpadding_beforeは0です。
入力契約・packing・ABI・応答形・エラー
各要素は空でないnameと、type文字列またはバイト単位のsizeとalignmentの両方を持ちます。packを省略すると自然な非packedレイアウトです。任意のabiは既定lp64で、llp64またはilp32も選べます。独自の不透明メンバは型表に頼らず正の整数sizeと2の累乗alignmentを与えます。offsetはご自身のダンプやコード生成と組み合わせてください。fieldsを空でないオブジェクト配列として含むJSON本体をPOSTしてください。既知の型にはchar、short、int、long、long long、float、double、bool、固定幅のintN_t/uintN_t族、アドレス幅整数のpointerまたはsize_tが含まれます。配列の別名としてmembersとlayoutを受け付けます。任意のpackは1・2・4・8のいずれかで#pragma pack(n)をモデル化し、各フィールドの実効整列は自然整列とpackの最小になります。空配列、未知の型名、2の累乗でないalignment、欠落したname、enum外のpackはinvalid_inputで失敗します。成功時の本体にはabi、packing有効時の任意pack、field_count、index・name・type・size・natural_alignment・effective_alignment・offset・padding_beforeを持つfields、struct_size、struct_alignment、trailing_padding、total_padding、used_bytes(メンバsizeの合計のみ)、method c_struct_offsetof、短いformula文字列が含まれます。例: 自然LP64のchar a、int b、char cはoffsetが0・4・8、struct_sizeが12、b前に内部パディング3バイトと末尾3バイトでsizeが4の倍数になります。本エンドポイントはCソースを出さず、offsetofとsizeofが示すレイアウト数値のみを返します。
構造体offset APIが役立つ場面・料金・上限
FFIとバインディング生成器は、LP64とWindowsのLLP64向けに決定的なoffsetofとsizeofが必要なため、同じスキーマ記述でLinux・macOS・Win64を対象にでき、ホストごとにプローブを再コンパイルする必要がありません。検証失敗は残高を消費しません。システムプログラマとリバースエンジニアは、バイナリプロトコルのパーサやカーネル構造ダンプを出荷する前に、手書きレイアウトがコンパイラと一致するかを構造体フィールドoffset計算機で確かめます。整列とpackingの演習では、学生にフィールド一覧とpack設定を渡し、サイズだけ足してパディングを忘れる誤りを純APIオラクルが不正と判定します。継続的インテグレーションはstruct_sizeと各offsetを固定し、フィールド追加やABIフラグ変更でテストが即失敗するようにします。実装は純粋なparseティアAのため、成功した呼び出しは毎回公開の基本料金$0.002で、モデルトークンも外部ネットワークも使いません。フィールド数は公開上限内に収め、移植性のために名前付き型を優先し、テストではoffsetを固定してください。
連携の活用例
バイナリプロトコルとダンプ解析
ワイヤデコーダを書く前、またはメモリダンプをC構造体と照合する前に、各フィールドのバイトoffsetと総sizeofを確認します。
整列とpackingの教育
学生が自然レイアウトと#pragma packを比較し、プローブをコンパイルせずにpadding_beforeとtrailing_paddingを確認できるようにします。
技術的な質問
C構造体のフィールドoffsetはどう計算しますか?
fieldsを{name, type}(または{name, size, alignment})の順序付き配列で送ってください。APIは標準のC切り上げ規則で各メンバのoffset・padding_before・struct_size・struct_alignmentを返します。
構造体フィールドoffset計算の料金は?
ブラウザツールは無料です。API要求は成功呼び出しごとにKIT前払い残高の$0.002です。無効な入力は課金されません。