天天看點

go語言指針和C指針差別,go語言指針與C指針的異同

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