What is the difference between go language and c language on pointers?
Difference: 1. Go language can use the new keyword to allocate memory and create pointers of specified types, but C language cannot. 2. The array name arr in the C language represents the address of the first element of the array, which is equivalent to "&arr[0]"; the array name arr in the Go language does not represent the address of the first element of the array, but represents the value of the entire array. 3. Go language does not support pointer arithmetic, but C language supports pointer arithmetic. 4.
The operating environment of this tutorial: Windows 7 system, GO version 1.18, Dell G3 computer.
C and Go are both languages with pointer concepts. This article mainly uses the similarities and differences between the two to deepen the understanding and use of Go pointers.
Operator
Both C and Go are the same:
&
Operator takes out the location of the variable The memory address*
operator takes out the value in the memory address pointed to by the pointer variable, also called "Dereference"
C language version example:
#include <stdio.h> int main() { int bar = 1; // 声明一个指向 int 类型的值的指针 int *ptr; // 通过 & 取出 bar 变量所在的内存地址并赋值给 ptr 指针 ptr = &bar; // 打印 ptr 的值(为地址),*prt 表示取出指针变量所指向的内存地址里面的值 printf("%p %d\n", ptr, *ptr); return (0); } // 输出结果: // 0x7ffd5471ee54 1</stdio.h>
Go language version example:
package main import "fmt" func main() { bar := 1 // 声明一个指向 int 类型的值的指针 var ptr *int // 通过 & 取出 bar 变量所在的内存地址并赋值给 ptr 指针 ptr = &bar // 打印 ptr 变量储存的指针地址,*prt 表示取出指针变量所指向的内存地址里面的值 fmt.Printf("%p %d\n", ptr, *ptr) } // 输出结果: // 0xc000086020 1
Go can also use the new
keyword to allocate memory Creates a pointer of the specified type.
// 声明一个指向 int 类型的值的指针 // var ptr *int ptr := new(int) // 通过 & 取出 bar 变量所在的内存地址并赋值给 ptr 指针 ptr = &bar
Array name and array first address
For an array
// C int arr[5] = {1, 2, 3, 4, 5}; // Go // 需要指定长度,否则类型为切片 arr := [5]int{1, 2, 3, 4, 5}
In C, the array name arr
represents The address of the first element of the array is equivalent to &arr[0]
and &arr
represents the first address of the entire array arr
// C // arr 数组名代表数组首元素的地址 printf("arr -> %p\n", arr); // &arr[0] 代表数组首元素的地址 printf("&arr[0] -> %p\n", &arr[0]); // &arr 代表整个数组 arr 的首地址 printf("&arr -> %p\n", &arr); // 输出结果: // arr -> 0061FF0C // &arr[0] -> 0061FF0C // &arr -> 0061FF0C
Run the program It can be found that the output values of arr
and &arr
are the same, but their meanings are completely different.
First of all, the array name arr
as an identifier is the address of arr[0]
, viewed from the perspective of &arr[0]
It is a pointer to a value of type int.
And &arr
is a pointer to a value of type int[5].
You can further verify the pointer offset
// C // 指针偏移 printf("arr+1 -> %p\n", arr + 1); printf("&arr+1 -> %p\n", &arr + 1); // 输出结果: // arr+1 -> 0061FF10 // &arr+1 -> 0061FF20
This involves the knowledge of offset: the movement of a pointer of type T
is based on sizeof(T)
is the moving unit.
arr 1
: arr is a pointer to a value of type int, so the offset is1*sizeof(int)
##&arr 1
: &arr is a pointer pointing to int[5], its offset is
1*sizeof(int)*5
arr and
&arr in C language. Next, let’s take a look at Go language
// 尝试将数组名 arr 作为地址输出 fmt.Printf("arr -> %p\n", arr) fmt.Printf("&arr[0] -> %p\n", &arr[0]) fmt.Printf("&arr -> %p\n", &arr) // 输出结果: // arr -> %!p([5]int=[1 2 3 4 5]) // &arr[0] -> 0xc00000c300 // &arr -> 0xc00000c300
&arr[0] and
&arr are consistent with C language.
arr in Go is no longer the address of the first element of the array, it represents the value of the entire array, so the output will prompt
%!p([5 ]int=[1 2 3 4 5])
Pointer arithmetic
A pointer is essentially an unsigned integer, representing a memory address. Pointers and integer values can be added and subtracted, such as the pointer offset example above:- Add
n
: A type is The pointer of
Tmoves to the high bit in units of
n*sizeof(T).
- minus
n
: A pointer of type
T, in units of
n*sizeof(T)Move low.
sizeof(T) represents the bytes occupied by the data type, for example
int is 4 bytes in a 32-bit environment , 8 bytes in 64-bit environment
#include <stdio.h> int main() { int arr[] = {1, 2, 3, 4, 5}; // ptr 是一个指针,为 arr 数组的第一个元素地址 int *ptr = arr; printf("%p %d\n", ptr, *ptr); // ptr 指针向高位移动一个单位,移向到 arr 数组第二个元素地址 ptr++; printf("%p %d\n", ptr, *ptr); return (0); } // 输出结果: // 0061FF08 1 // 0061FF0C 2</stdio.h>Here
ptr moved from
0061FF08
sizeof( int) = 4 bytes to
0061FF0C, pointing to the address of the next array element
package main import "fmt" func main() { arr := [5]uint32{1, 2, 3, 4, 5} // ptr 是一个指针,为 arr 数组的第一个元素地址 ptr := &arr[0] fmt.Println(ptr, *ptr) // ptr 指针向高位移动一个单位,移向到 arr 数组第二个元素地址 ptr++ fmt.Println(ptr, *ptr) } // 输出结果: // 编译报错: // .\main.go:13:5: invalid operation: ptr++ (non-numeric type *uint32)
编译报错 *uint32
非数字类型,不支持运算,说明 Go 是不支持指针运算的。
这个其实在 Go Wiki[1] 中的 Go 从 C++ 过渡文档中有提到过:Go has pointers but not pointer arithmetic.
Go 有指针但不支持指针运算。
另辟蹊径
那还有其他办法吗?答案当然是有的。
在 Go 标准库中提供了一个 unsafe
包用于编译阶段绕过 Go 语言的类型系统,直接操作内存。
我们可以利用 unsafe
包来实现指针运算。
func Alignof(x ArbitraryType) uintptr func Offsetof(x ArbitraryType) uintptr func Sizeof(x ArbitraryType) uintptr type ArbitraryType func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType type IntegerType type Pointer func Add(ptr Pointer, len IntegerType) Pointer
核心介绍:
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
即可
代码实现:
package main import ( "fmt" "unsafe" ) func main() { arr := [5]uint32{1, 2, 3, 4, 5} ptr := &arr[0] // ptr(*uint32类型) => one(unsafe.Pointer类型) one := unsafe.Pointer(ptr) // one(unsafe.Pointer类型) => *uint32 fmt.Println(one, *(*uint32)(one)) // one(unsafe.Pointer类型) => one(uintptr类型) 后向高位移动 unsafe.Sizeof(arr[0]) = 4 字节 // twoUintptr := uintptr(one) + unsafe.Sizeof(arr[0]) // !!twoUintptr 不能作为临时变量 // uintptr 类型的临时变量只是一个无符号整数,并不知道它是一个指针地址,可能被 GC // 运算完成后应该直接转换回 unsafe.Pointer : two := unsafe.Pointer(uintptr(one) + unsafe.Sizeof(arr[0])) fmt.Println(two, *(*uint32)(two)) } // 输出结果: // 0xc000012150 1 // 0xc000012154 2
甚至还可以更改结构体的私有成员:
// model/model.go package model import ( "fmt" ) type M struct { foo uint32 bar uint32 } func (m M) Print() { fmt.Println(m.foo, m.bar) } // main.go package main import ( "example/model" "unsafe" ) func main() { m := model.M{} m.Print() foo := unsafe.Pointer(&m) *(*uint32)(foo) = 1 bar := unsafe.Pointer(uintptr(foo) + 4) *(*uint32)(bar) = 2 m.Print() } // 输出结果: // 0 0 // 1 2
小 Tips
Go 的底层 slice
切片源码就使用了 unsafe
包
// slice 切片的底层结构 type slice struct { // 底层是一个数组指针 array unsafe.Pointer // 长度 len int // 容量 cap int }
总结
Go 可以使用
&
运算符取地址,也可以使用new
创建指针Go 的数组名不是首元素地址
Go 的指针不支持运算
Go 可以使用
unsafe
包打破安全机制来操控指针,但对我们开发者而言,是 "unsafe" 不安全的
更多编程相关知识,请访问:编程视频!!
The above is the detailed content of What is the difference between go language and c language on pointers?. For more information, please follow other related articles on the PHP Chinese website!

Golangisidealforperformance-criticalapplicationsandconcurrentprogramming,whilePythonexcelsindatascience,rapidprototyping,andversatility.1)Forhigh-performanceneeds,chooseGolangduetoitsefficiencyandconcurrencyfeatures.2)Fordata-drivenprojects,Pythonisp

Golang achieves efficient concurrency through goroutine and channel: 1.goroutine is a lightweight thread, started with the go keyword; 2.channel is used for secure communication between goroutines to avoid race conditions; 3. The usage example shows basic and advanced usage; 4. Common errors include deadlocks and data competition, which can be detected by gorun-race; 5. Performance optimization suggests reducing the use of channel, reasonably setting the number of goroutines, and using sync.Pool to manage memory.

Golang is more suitable for system programming and high concurrency applications, while Python is more suitable for data science and rapid development. 1) Golang is developed by Google, statically typing, emphasizing simplicity and efficiency, and is suitable for high concurrency scenarios. 2) Python is created by Guidovan Rossum, dynamically typed, concise syntax, wide application, suitable for beginners and data processing.

Golang is better than Python in terms of performance and scalability. 1) Golang's compilation-type characteristics and efficient concurrency model make it perform well in high concurrency scenarios. 2) Python, as an interpreted language, executes slowly, but can optimize performance through tools such as Cython.

Go language has unique advantages in concurrent programming, performance, learning curve, etc.: 1. Concurrent programming is realized through goroutine and channel, which is lightweight and efficient. 2. The compilation speed is fast and the operation performance is close to that of C language. 3. The grammar is concise, the learning curve is smooth, and the ecosystem is rich.

The main differences between Golang and Python are concurrency models, type systems, performance and execution speed. 1. Golang uses the CSP model, which is suitable for high concurrent tasks; Python relies on multi-threading and GIL, which is suitable for I/O-intensive tasks. 2. Golang is a static type, and Python is a dynamic type. 3. Golang compiled language execution speed is fast, and Python interpreted language development is fast.

Golang is usually slower than C, but Golang has more advantages in concurrent programming and development efficiency: 1) Golang's garbage collection and concurrency model makes it perform well in high concurrency scenarios; 2) C obtains higher performance through manual memory management and hardware optimization, but has higher development complexity.

Golang is widely used in cloud computing and DevOps, and its advantages lie in simplicity, efficiency and concurrent programming capabilities. 1) In cloud computing, Golang efficiently handles concurrent requests through goroutine and channel mechanisms. 2) In DevOps, Golang's fast compilation and cross-platform features make it the first choice for automation tools.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Dreamweaver Mac version
Visual web development tools

WebStorm Mac version
Useful JavaScript development tools

Zend Studio 13.0.1
Powerful PHP integrated development environment