33

私はGoを見ています。これは非常に有望に見えます。たとえば、go構造体のサイズを取得する方法を理解しようとしています。

type Coord3d struct {
    X, Y, Z int64
}

もちろん24バイトであることは知っていますが、プログラムで知りたいのですが。

これを行う方法について何かアイデアはありますか?

4

6 に答える 6

45
import unsafe "unsafe"

/* Structure describing an inotify event.  */
type INotifyInfo struct {
    Wd     int32  // Watch descriptor
    Mask   uint32 // Watch mask
    Cookie uint32 // Cookie to synchronize two events
    Len    uint32 // Length (including NULs) of name
}

func doSomething() {
    var info INotifyInfo
    const infoSize = unsafe.Sizeof(info)
    ...
}

注: OPは間違っています。unsafe.Sizeofは、Coord3d構造体の例で24を返します。以下のコメントを参照してください。

于 2010-01-22T07:20:37.657 に答える
42

Roger は、 unsafeパッケージのSizeOfメソッドの使用方法を既に示しました。関数によって返される値に依存する前に、必ずこれを読んでください。

サイズには、x によって参照される可能性のあるメモリは含まれません。たとえば、x がスライスの場合、Sizeof は、スライスが参照するメモリのサイズではなく、スライス記述子のサイズを返します。

これに加えて、いくつかの単純なルールを使用して構造体のサイズを簡単に計算する方法を説明したかったのです。そして、便利なサービスを使用して直感を検証する方法。


サイズは、それが構成する型と構造体のフィールドの順序によって異なります (異なるパディングが使用されるため)。これは、同じフィールドを持つ 2 つの構造体のサイズが異なる可能性があることを意味します。

たとえば、この構造体のサイズは 32 になります

struct {
    a bool
    b string
    c bool
}

わずかな変更でサイズは 24になります(フィールドの順序がよりコンパクトになったため、25%の違いがあります)。

struct {
    a bool
    c bool
    b string
}

ここに画像の説明を入力 ここに画像の説明を入力

写真からわかるように、2 番目の例では、パディングの 1 つを削除し、前のパディングを利用するためにフィールドを移動しました。アラインメントは、1、2、4、または 8 にすることができます。パディングは、アラインメントを埋めるために変数を埋めるために使用されたスペースです (基本的に無駄なスペース)。

このルールを知り、次のことを覚えておいてください。

  • bool、int8/uint8 は 1 バイト
  • int16、uint16 - 2 バイト
  • int32、uint32、float32 - 4 バイト
  • int64、uint64、float64、ポインター - 8 バイト
  • 文字列 - 16 バイト (8 バイトの 2 つのアラインメント)
  • どのスライスも 24 バイト (8 バイトの 3 つのアラインメント) を必要とします。だから[]bool[][][]string同じです(最初に追加した引用を読み直すことを忘れないでください)
  • 長さの配列は* バイトの型を取りますnn

パディング、アラインメント、およびサイズ (バイト単位) の知識があれば、構造体を改善する方法をすぐに理解できます (ただし、サービスを使用して直感を検証することは理にかなっています)。

于 2016-06-26T01:01:03.237 に答える
9

binary.TotalSize もオプションですが、unsafe.Sizeof: binary.TotalSize にはスライスの内容のサイズが含まれますが、unsafe.Sizeof は最上位の記述子のサイズのみを返します。TotalSize の使用例を次に示します。

package main

import (
    "encoding/binary"
    "fmt"
    "reflect"
)

type T struct {
    a uint32
    b int8
}

func main() {
    var t T
    r := reflect.ValueOf(t)
    s := binary.TotalSize(r)

    fmt.Println(s)
}
于 2010-01-23T19:28:20.883 に答える
2

バイナリパッケージを参照してください。具体的TotalSizeな方法は

于 2010-01-22T02:31:21.863 に答える
1

これは変更される可能性がありますが、最後に確認したところ、構造のアラインメントに関連する未解決のコンパイラ バグ (bug260.go) があります。最終結果として、構造体をパックしても期待した結果が得られない可能性があります。これは、コンパイラ 6g バージョン 5383 リリース.2010-04-27 リリース用でした。結果には影響しないかもしれませんが、注意が必要です。

更新: リリース 2010-05-04 の時点で、go テスト スイートに残っている唯一のバグは、上記の bug260.go です。

布袋

于 2010-05-01T06:18:15.603 に答える