總結一下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
#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[]