今天小编给大家分享一下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 语言示例:在这里
Go 语言示例:ptr++
从 0061FF08
移动了 sizeof(int) = 4
个字节到 0061FF0C
,指向了下一个数组元素的地址编译报错
这个其实在 Go Wiki[1] 中的 Go 从 C++ 过渡文档中有提到过:*uint32
非数字类型,不支持运算,说明 Go 是不支持指针运算的。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)))
的结果为 4
unsafe.Offsetof
: 函数的参数必须是一个字段 x.f,然后返回 f 字段相对于 x 起始地址的偏移量,用于计算结构体成员的偏移量原理:Go 的 uintptr
类型存储的是地址,且支持数学运算*T
(任意指针类型) 和 unsafe.Pointer
不能运算,但是 unsafe.Pointer
可以和 *T
、 uintptr
互相转换因此,将 *T
转换为 unsafe.Pointer
后再转换为 uintptr
,uintptr
进行运算之后重新转换为 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中引入组件的方式有以下两种1.使用import方法导入…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。