分享
  1. 首页
  2. 文章

golang指针与C指针的异同

yunfound · · 3711 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

总结一下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[]

有疑问加站长微信联系(非本文作者)

本文来自:开源中国博客

感谢作者:yunfound

查看原文:golang指针与C指针的异同

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
3711 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏