Golang - 结构、初始化和 memcpy - 什么是正确的方法?

Golang - structs, initializing and memcpy - what is the proper way?

我是 Go 的新手,我想翻译一些 C/C++ 我必须去但没能做到的代码。问题出在两个地方:如何初始化我定义的结构以及如何执行 "memcopy"

我说的代码是这样的:http://play.golang.org/p/e8N255qEAk 第 69 和 74 行。

我想要"translate"去执行的C/C++代码是这样的:

            typedef char xchr;
            typedef int xint;
            typedef double xdob;
            typedef float xflt;
            typedef struct
            {
               xint p; 
               xdob lat_lon_ele[3];
               xflt psi_the_phi[3];
               xflt gear_flap_vect[3];
            }VEH1;

            avio.p = 0;
            avio.lat_lon_ele[0] = 47.460058;
            avio.lat_lon_ele[1] = -122.32104;
            avio.lat_lon_ele[2] = 8000.000;

            avio.psi_the_phi[0] = 110.5;
            avio.psi_the_phi[1] = 0.0;
            avio.psi_the_phi[2] = 0.0;

            avio.gear_flap_vect[0] = 1.0;
            avio.gear_flap_vect[1] = 0.0;
            avio.gear_flap_vect[2] = 0.0;

            VEH1* av = &avio;

            xchr data_send[6];
            data_send[0]='V';
            data_send[1]='E';
            data_send[2]='H';
            data_send[3]='1';
            data_send[4]=0;

            memcpy(&data_send[5],av,sizeof(VEH1)); // load in the data

Go 代码如下所示:

            type xchr int8
            type xint int
            type xdob float64
            type xflt float32

            type VEH1 struct {
                p              xint
                lat_lon_ele    [3]xdob
                psi_the_phi    [3]xflt
                gear_flap_vect [3]xflt
            }

            type VEHA struct {
                num_p xint

                lat_lon_ele    [10][3]xdob
                psi_the_phi    [10][3]xflt
                gear_flap_vect [10][3]xflt

                lat_view, lon_view, ele_view xdob
                psi_view, the_view, phi_view xflt
            }


            var avio VEH1
            avio = &VEH1{0, {47.460058, -122.32104, 8000.000}, {110.5, 0.0, 0.0}, {1.0, 0.0, 0.0}}

            data_send := [6]xchr{'V', 'E', 'H', '1', 0, 0}
            copy(data_send[5:5], avio);

谢谢!

所以基本上给出了这些基本类型:

type xchr int8
type xint int
type xdob float64
type xflt float32

您想复制以下 struct 类型值的字节(内存表示):

type VEH1 struct { // 52 bytes total
    p              xint    // 4 bytes (READ BELOW)
    lat_lon_ele    [3]xdob // 24 bytes
    psi_the_phi    [3]xflt // 12 bytes
    gear_flap_vect [3]xflt // 12 bytes
}

请注意,Go 中 int 的长度取决于平台,它可能是 32 位或 64 位,具体取决于您编译到的目标体系结构。这将导致依赖于平台的行为,所以让我们暂时将其修复为 int32

type xint int32

上面struct的字节大小是这样计算的。如果你需要int64,只需更改它并在大小计算中添加额外的4个字节。

接下来,您需要将结果放入一个元素类型为 xchr 的数组中。你需要一个足够大的数组,即 "prefix" 是 "VEH1" 后面跟着上面的数据 struct。所以它的大小必须是 4+sizeof(VEH1)56.

在Go中将一种类型的字节复制到另一种类型的内存中space,可以做到unsafe package and its general Pointer类型。任何指针都可以转换为unsafe.Pointerunsafe.Pointer可以转换为任何指针类型,所以这是你在不同指针类型之间的"gateway"。

可以取VHE1struct值的地址,将其转换为Pointer,并将结果Pointer转换为指向目标数据的指针类型。取消引用指针,现在您已经拥有其他类型的值。

内置函数 copy() 只能与切片一起使用,因此首先您需要对数据数组进行切片才能将它们传递给 copy()

你可以这样做:

avio := VEH1{0, [3]xdob{47.460058, -122.32104, 8000.000},
    [3]xflt{110.5, 0.0, 0.0}, [3]xflt{1.0, 0.0, 0.0}}
fmt.Printf("%+v\n", avio)

pavio := unsafe.Pointer(&avio)
pavio_arr := *((*[52]xchr)(pavio))

data_send := [56]xchr{'V', 'E', 'H', '1'}
n := copy(data_send[4:], pavio_arr[:])
fmt.Printf("Copied %d bytes\n", n)

fmt.Printf("%+v\n", data_send)

输出,包裹以适合屏幕:

{p:0 lat_lon_ele:[47.460058 -122.32104 8000] psi_the_phi:[110.5 0 0]
    gear_flap_vect:[1 0 0]}
Copied 52 bytes
[86 69 72 49 0 0 0 0 0 0 0 0 -81 33 56 46 -29 -70 71 64 77 45 91 -21 -117
    -108 94 -64 0 0 0 0 0 64 -65 64 0 0 -35 66 0 0 0 0 0 0 0 0 0 0 -128 63 0 0 0 0]

尝试 Go Playground 上的工作演示。

结果为[]byte

如果你想要 []byte 结果(例如,你想将结果写入 io.Writer),然后使用 [56]byte 键入 data_send,当然还有投 pavio*[52]byte:

pavio := unsafe.Pointer(&avio)
pavio_arr := *((*[52]byte)(pavio))

data_send := [56]byte{'V', 'E', 'H', '1'}
n := copy(data_send[4:], pavio_arr[:])