<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## 緣由 現在有個應用場景,我們要在`go`中獲取`C`結構體數組中的值。在`C`語言中,對于結構體數組,我們可以利用指針的偏移量來獲取我們想要的值的位置。在`go`中我們怎么使用`C`指針和偏移量進行運算呢?下面的文字中`C`指的是`C語言` ## 利用cgo作為橋梁,遍歷C結構體數組 `unsafe.Pointer`在C語言中類似`void*`,但是在go中無法用unsafe.Pointer進行運算。 不過`go`中有一種類型`uintptr`可以與`unsafe.Pointer`進行互相轉換,并且可以進行運算。于是我有如下思路: * 利用`unsafe.Pointer`將C指針轉化為go指針,也就是獲取結構體數組的地址 * 然后轉成`uintptr` * 計算出元素偏移量,根據元素偏移量取出元素 ## 舉例 聲明一個C數組 ```cpp #include <stdio.h> #include <stdlib.h> typedef struct { char *name; int age; }person; //new一個長度為n的person結構體數組 person* NewPersonArray(int n) { person *pon; pon =(person*)malloc(sizeof(person)*n); //初始化name for(int i = 0; i<n;i++){ pon[i].name = (char*)malloc(sizeof(char)*10); pon[i].age = i; sprintf(pon[i].name, "name:%d", i); } return pon; } //釋放內存 void freePersonArray(person* pon, int len) { for (int i = 0; i < len; i ++){ free(pon[i].name); } free(pon); } ``` C已經做好了內存分配和內存釋放,接下來看看在go中 怎么使用C的數據 ```go func main() { var person *C.person n := 10 person = C.NewPersonArray(C.int(n)) //new一個長度為n的person數組 //用go的方式遍歷C數組 for i:=0; i < n; i++ { p := *(*C.person)(unsafe.Pointer(uintptr(unsafe.Pointer(person)) + uintptr(C.sizeof_person*C.int(i)))) fmt.Printf("i: %d, p.name: %s, p.age: %d\n", i, C.GoString(p.name), int(p.age) ) } C.freePersonArray(person, C.int(n)) } ``` 關鍵的一步是計算偏移量并進行運算: ```go p := *(*C.person)(unsafe.Pointer(uintptr(unsafe.Pointer(person)) + uintptr(C.sizeof_person*C.int(i)))) ``` 我們來把這個步驟分解一下: 第一步,將C指針轉化為`unsafe.Pointer`,然后轉化為`uintptr` ```go uintptr(unsafe.Pointer(person)) ``` 第二步,計算每個結構體所占用的大小 `C.sizeof_person`,并乘以 `i`,然后轉化為`uintptr`,得到偏移量, 這個`person`是結構體名字。 ```go uintptr(C.sizeof_person*C.int(i)) ``` 第三步,把第一步的`uintptr`和第二步得到的偏移量相加,得到一個新的`uintptr`值, ```go uintptr(unsafe.Pointer(person)) + uintptr(C.sizeof_person*C.int(i)) ``` 第四步,把第三部得到的`uintptr`轉化為`unsafe.Pointer`,然后再強制轉化為`*C.person`,這就類似`C語言`中的指針運算:`指針+偏移量`。 ```go p := *(*C.person)(unsafe.Pointer(uintptr(unsafe.Pointer(person)) + uintptr(C.sizeof_person*C.int(i)))) ``` ## 完整代碼 通過上面的四個步驟就可以利用`go`語言從`C`結構體數組中取出元素,完整代碼如下: ```go package main /* #include <stdio.h> #include <stdlib.h> typedef struct { char *name; int age; }person; person* NewPersonArray(int n) { person *pon; pon =(person*)malloc(sizeof(person)*n); //初始化name for(int i = 0; i<n;i++){ pon[i].name = (char*)malloc(sizeof(char)*10); pon[i].age = i; sprintf(pon[i].name, "name:%d", i); } return pon; } void freePersonArray(person* pon, int len) { for (int i = 0; i < len; i ++){ free(pon[i].name); } free(pon); } */ import "C" import ( "fmt" "unsafe" ) func main() { var person *C.person n := 10 person = C.NewPersonArray(C.int(n)) //new一個長度為n的person數組 //用go的方式遍歷C數組 for i:=0; i < n; i++ { p := *(*C.person)(unsafe.Pointer(uintptr(unsafe.Pointer(person)) + uintptr(C.sizeof_person*C.int(i)))) fmt.Printf("i: %d, p.name: %s, p.age: %d\n", i, C.GoString(p.name), int(p.age) ) } C.freePersonArray(person, C.int(n)) } ``` 輸出 ``` i: 0, p.name: name:0, p.age: 0 i: 1, p.name: name:1, p.age: 1 i: 2, p.name: name:2, p.age: 2 i: 3, p.name: name:3, p.age: 3 i: 4, p.name: name:4, p.age: 4 i: 5, p.name: name:5, p.age: 5 i: 6, p.name: name:6, p.age: 6 i: 7, p.name: name:7, p.age: 7 i: 8, p.name: name:8, p.age: 8 i: 9, p.name: name:9, p.age: 9 ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看