go语言和c语言在指针上有哪些区别


今天小编给大家分享一下go语言和c语言在指针上有哪些区别的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。 区别:1、go语言可以使用new关键字来分配内存创建指定类型的指针,而c语言不行。2、c语言中数组名arr代表的是数组首元素的地址,相当于“&arr[0]”;go语言中数组名arr不代表数组首元素的地址,代表的是整个数组的值。3、go语言不支持指针运算,而c语言支持指针运算。C 和 Go 都相同:& 运算符取出变量所在的内存地址* 运算符取出指针变量所指向的内存地址里面的值,也叫 “ 解引用 ”C 语言版示例:Go 语言版示例:

packagemain

import"fmt"

funcmain(){
bar:=1
//声明一个指向int类型的值的指针
varptr*int
//通过&取出bar变量所在的内存地址并赋值给ptr指针
ptr=&bar
//打印ptr变量储存的指针地址,*prt表示取出指针变量所指向的内存地址里面的值
fmt.Printf("%p%dn",ptr,*ptr)
}

//输出结果:
//0xc0000860201

Go 还可以使用 new 关键字来分配内存创建指定类型的指针。

//声明一个指向int类型的值的指针
//varptr*int
ptr:=new(int)
//通过&取出bar变量所在的内存地址并赋值给ptr指针
ptr=&bar

Go 还可以使用 new 关键字来分配内存创建指定类型的指针。
对于一个数组在 C 中,数组名 arr 代表的是数组首元素的地址,相当于 &arr[0]
&arr 代表的是整个数组 arr 的首地址运行程序可以发现 arr&arr 的输出值是相同的,但是它们的意义完全不同。
首先数组名 arr 作为一个标识符,是 arr[0] 的地址,从 &arr[0] 的角度去看就是一个指向 int 类型的值的指针。而 &arr 是一个指向 int[5] 类型的值的指针。可以进一步对其进行指针偏移验证这里涉及到偏移量的知识:一个类型为 T 的指针的移动,是以 sizeof(T) 为移动单位的。
arr+1 : arr 是一个指向 int 类型的值的指针,因此偏移量为 1*sizeof(int)&arr+1 : &a免费云主机域名mp;arr 是一个指向 int[5] 的指针,它的偏移量为 1*sizeof(int)*5到这里相信你应该可以理解 C 语言中的 arr&arr 的区别了吧,接下来看看 Go 语言&arr[0]&arr 与 C 语言一致。
但是数组名 arr 在 Go 中已经不是数组首元素的地址了,代表的是整个数组的值,所以输出时会提示 %!p([5]int=[1 2 3 4 5])指针本质上就是一个无符号整数,代表了内存地址。指针和整数值可以进行加减法运算,比如上文的指针偏移例子:加n : 一个类型为 T 的指针,以 n*sizeof(T) 为单位向高位移动。减n : 一个类型为 T 的指针,以 n*sizeof(T) 为单位向低位移动。其中 sizeof(T) 代表的是数据类型占据的字节,比如 int 在 32 位环境下为 4 字节,64 位环境下为 8 字节C 语言示例:在这里 ptr++0061FF08 移动了 sizeof(int) = 4 个字节到 0061FF0C ,指向了下一个数组元素的地址
Go 语言示例:编译报错 *uint32 非数字类型,不支持运算,说明 Go 是不支持指针运算的。
这个其实在 Go Wiki[1] 中的 Go 从 C++ 过渡文档中有提到过:Go has pointers but not pointer arithmetic.Go 有指针但不支持指针运算。另辟蹊径那还有其他办法吗?答案当然是有的。在 Go 标准库中提供了一个 unsafe 包用于编译阶段绕过 Go 语言的类型系统,直接操作内存。我们可以利用 unsafe 包来实现指针运算。核心介绍:
uintptr : Go 的内置类型。是一个无符号整数,用来存储地址,支持数学运算。常与 unsafe.Pointer 配合做指针运算unsafe.Pointer : 表示指向任意类型的指针,可以和任何类型的指针互相转换(类似 C 语言中的 void* 类型的指针),也可以和 uintptr 互相转换unsafe.Sizeof : 返回操作数在内存中的字节大小,参数可以是任意类型的表达式,例如 fmt.Println(unsafe.Sizeof(uint32(0))) 的结果为 4unsafe.Offsetof : 函数的参数必须是一个字段 x.f,然后返回 f 字段相对于 x 起始地址的偏移量,用于计算结构体成员的偏移量原理:Go 的 uintptr 类型存储的是地址,且支持数学运算*T (任意指针类型) 和 unsafe.Pointer 不能运算,但是 unsafe.Pointer 可以和 *Tuintptr 互相转换因此,将 *T 转换为 unsafe.Pointer 后再转换为 uintptruintptr 进行运算之后重新转换为 unsafe.Pointer => *T 即可代码实现:甚至还可以更改结构体的私有成员:

//model/model.go

packagemodel

import(
"fmt"
)

typeMstruct{
foouint32
baruint32
}

func(mM)Print(){
fmt.Println(m.foo,m.bar)
}

//main.go

packagemain

import(
"example/model"
"unsafe"
)

funcmain(){
m:=model.M{}
m.Print()

foo:=unsafe.Pointer(&m)
*(*uint32)(foo)=1
bar:=unsafe.Pointer(uintptr(foo)+4)
*(*uint32)(bar)=2

m.Print()
}

//输出结果:
//00
//12

Go 的底层 slice 切片源码就使用了 unsafe 包以上就是“go语言和c语言在指针上有哪些区别”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注百云主机行业资讯频道。

相关推荐: vue引入组件的方式有哪些

这篇文章主要介绍“vue引入组件的方式有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强免费云主机域名,希望这篇“vue引入组件的方式有哪些”文章能帮助大家解决问题。在vue中引入组件的方式有以下两种1.使用import方法导入…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 02/24 17:40
Next 02/24 17:42

相关推荐