這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
總結一下golang中的指標與C語言的指標的用法。
總體一致:
C的代碼:
int *number;number = (int*) malloc(sizeof(int));*number = 3;printf("%d\n", *number);
golang的代碼:
var pointer *int;pointer = new(int);*pointer = 3;fmt.Println(*pointer);
多重指標情況:
C的代碼:
int **outer;int *inter;inter = (int*) malloc(sizeof(int));*inter = 3;outer = &inter;// 地址一樣printf("%p\n", inter);printf("%p\n", *outer);// 值一樣printf("%d\n", *inter);printf("%d\n", *outer);
golang的代碼:
var outer **int;var inter *int;inter = new(int);*inter = 3;outer = &inter;// 地址一樣fmt.Println(inter);fmt.Println(*outer);// 值一樣fmt.Println(*inter);fmt.Println(**outer);
C語言的下面這種方式在golang裡實現:
int **outer;int *inter;inter = (int*) malloc(sizeof(int));outer = (int*) malloc(sizeof(int));*inter = 3;*outer = inter;// 地址一樣printf("%p\n", inter);printf("%p\n", outer);// 值一樣printf("%d\n", *inter);printf("%d\n", **outer);
在golang中:
var inter *int;var outer **int;inter = new(int);*inter = 3;outer = new(*int);*outer = inter;// 地址一樣fmt.Println(inter);fmt.Println(*outer);// 值一樣fmt.Println(*inter);fmt.Println(**outer);
上面都是在玩指標, 下面看看基本的資料結構.
基本的資料結構有: 數組與結構體 (map和樹之類的不在討論範圍)
golang中的數組與C中的數組有很大的差別
golang中的數組是這樣說的: Arrays are values, not implicit pointers as in C.
- 數組做參數時, 需要被檢查長度.
- 變數名不等於數組開始指標!
- 不支援C中的*(ar + sizeof(int))方式的指標移動. 需要使用到unsafe包
- 如果p2array為指向數組的指標, *p2array不等於p2array[0]
例子1 數組做參數時, 需要被檢查長度.
func use_array(args [4]int){ args[1] = 100;}func main() { var args = [5]int{1, 2, 3, 4, 5}; use_array(args); fmt.Println(args);}
編譯出錯: cannot use args (type [5]int) as type [4]int in function argument, 需要有長度上的檢查
例子2 變數名不等於數組開始指標!
func use_array(args [4]int){ args[1] = 100;}func main() { var args = [5]int{1, 2, 3, 4, 5}; use_array(args); fmt.Println(args);}
輸出結果是 [1 2 3 4], 沒有儲存結果, 數組名的用法與C的不一樣. 在golang裡是這樣的:
// 又長度檢查, 也為地址傳參func use_array(args *[4]int){ args[1] = 100; //但是使用還是和C一致,不需要別加"*"操作符}func main() { var args = [4]int{1, 2, 3, 4}; use_array(&args); // 數組名已經不是表示地址了, 需要使用"&"得到地址 fmt.Println(args);}
例子3 如果p2array為指向數組的指標,*p2array不等於p2array[0]
對比一下C和golang在這方面的差別:
void main(int argc, char *argv[]){ int *p2array; p2array = (int*) malloc(sizeof(int) * 3); // 等於p2array[0] *p2array = 0; printf("%d\n", *p2array + 1);}
輸出為1
func main() { var p2array *[3]int; p2array = new([3]int); fmt.Printf("%x\n", *p2array + 1); // 不管p2array是指標變數還是陣列變數, 都只能使用"[]"方式使用}
報錯.
golang中的結構體也與C中的有差別
下面的方式是相當一致的:
C版本的:
typedef struct { int x; int y;} Point;Point p;p.x = 10;p.y = 20;// 開始地址printf("%p\n", &p);// 某元素地址printf("%p\n", &(p.x));
golang版本的:
type Point struct{ x int; y int;};var p Point;p.x = 10;p.y = 20;fmt.Printf("%p\n", &p);fmt.Printf("%p\n", &(p.x));
使用allocate的方式:
C代碼:
typedef struct { int x; int y;} Point;Point *p;p = (Point *) malloc(sizeof(Point));p->x = 10;p->y = 20;// 開始地址printf("%p\n", p); // 地址// 某元素地址printf("%p\n", &(p->x));
golang代碼:
type Point struct{ x int; y int;}var p *Point;p = new(Point);p.x = 10;p.y = 20;fmt.Printf("%p\n", p); // 地址fmt.Printf("%p\n", &(p.x));
也可以說是一樣的, 只不過在使用結構中的元素時沒有了"->"操作符:
There is no -> notation for structure pointers. Go provides the indirection for you.
結構體的地址傳參與數組的方式一樣, 當然, 和C的風格也是一模一樣的. 如下例子:
C代碼:
#include #include typedef struct{ int x; int y;} Point;void use_struct(Point *arg){ arg->x = 100;}void main(int argc, char *argv[]){ Point *p; p = (Point *) malloc(sizeof(Point)); p->x = 10; p->y = 20; use_struct(p); printf("%d\n", p->x);}
golang代碼:
import "fmt"type Point struct{ x int; y int;};func use_sturct( p *Point ){ p.x = 100;}func main() { var p *Point; p = new(Point); p.x = 10; p.y = 20; use_sturct(p); fmt.Printf("%d\n", p.x);}
總的來說......
在傳參方面, 大體上看與C的相同:
f(ar); // passes a copy of ar fp(&ar); // passes a pointer to ar
* 只是變數名是不是表示首個地址 有區別
"&" 與C語言一樣是得到變數的指標. 與C有點不同, 取golang中指標指標的內容的值是不需要使用"*"操作符的, 但是指標的指標(或者繼續多層時)需要顯式使用"*"符號.
在 http://golang.org/doc/go_spec.html#Selectors 一節中有描述。
* 三層以上的指標使用是比較少的. 兩層還是常見, 如main函數的參數char * argv[]