总结一下golang中的指针与C语言的指针的用法。
总体一致:
C的代码:
1
2
3
4
|
int
*number;
number = (
int
*)
malloc
(
sizeof
(
int
));
*number = 3;
printf
(
"%d\n"
, *number);
|
1
2
3
4
|
var pointer *
int
;
pointer =
new
(
int
);
*pointer = 3;
fmt.Println(*pointer);
|
多重指针情况:
C的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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);
|
1
2
3
4
5
6
7
8
9
10
11
|
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里实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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);
|
1
2
3
4
5
6
7
8
9
10
11
12
|
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]
1
2
3
4
5
6
7
8
9
|
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 变量名不等于数组开始指针!
1
2
3
4
5
6
7
8
9
|
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
5
6
7
8
9
10
|
// 又长度检查, 也为地址传参
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在这方面的差别:
1
2
3
4
5
6
7
8
|
void
main(
int
argc,
char
*argv[]){
int
*p2array;
p2array = (
int
*)
malloc
(
sizeof
(
int
) * 3);
//等于p2array[0]
*p2array = 0;
printf
(
"%d\n"
, *p2array + 1);
}
* 输出为1
|
1
2
3
4
5
6
|
func main() {
var p2array *[3]
int
;
p2array =
new
([3]
int
);
fmt.Printf(
"%x\n"
, *p2array + 1);
//不管p2array是指针变量还是数组变量, 都只能使用"[]"方式使用
}
* 报错.
|
golang中的结构体也与C中的有差别
下面的方式是相当一致的:
C版本的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
typedef
struct
{
int
x;
int
y;
} Point;
Point p;
p.x = 10;
p.y = 20;
//开始地址
printf
(
"%p\n"
, &p);
//某元素地址
printf
(
"%p\n"
, &(p.x));
|
1
2
3
4
5
6
7
8
9
10
|
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代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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));
|
1
2
3
4
5
6
7
8
9
10
11
|
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));
|
也可以说是一样的, 只不过在使用结构中的元素时没有了"->"操作符:
1
|
There is no -> notation for structure pointers. Go provides the indirection for you.
|
结构体的地址传参与数组的方式一样, 当然, 和C的风格也是一模一样的. 如下例子:
C代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#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);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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的相同:
1
2
|
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[]