這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
總結一下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.
0. 數組做參數時, 需要被檢查長度.
1. 變數名不等於數組開始指標!
2. 不支援C中的*(ar + sizeof(int))方式的指標移動. 需要使用到unsafe包
3. 如果p2array為指向數組的指標, *p2array不等於p2array[0]
例子0 數組做參數時, 需要被檢查長度.
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, 需要有長度上的檢查
例子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);}
輸出結果是 [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);}
例子2 如果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 <stdio.h>#include <stdlib.h>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[]