首页 > 其他分享 >结构体和指针

结构体和指针

时间:2024-11-13 21:19:45浏览次数:1  
标签:fmt 指针 地址 Println main ptr 结构

指针与结构体

【1】、指针

变量是一个占位符,底层指向是一个内存地址。

&:取地址符 &a:取出a变量的地址

1、指针的概念

b内存地址 0x11111111111, 值:500 var b int = 500
a指针变量,指向了一个内存地址 0x11111111111

变量a持有了变量b的地址。这个就是a指向了b

package main

import "fmt"

func main() {
	// 指针
	var a int = 10
	// b存储的就是a的地址
	// * 取出指向的地址的值
	var b = &a
	fmt.Println("a的地址", &a)
	fmt.Println("b指向的地址:", b)
	fmt.Println("b自己的地址:", &b)
	fmt.Println("b指向的地址的值:", *b)
	//a的地址 0xc0000a6058
	//b指向的地址: 0xc0000a6058
	//b自己的地址: 0xc0000ca018
	//b指向的地址的值: 10

	*b = 20
	fmt.Println("a的值:", a) // a的值:20

}

2、指针如何使用

package main

import "fmt"

/*
1、定义指针变量
2、为指针变量赋值  &
3、访问指针变量中地址所指向的值   *
* :在指针类型前面加上 * 号,就是来获取指针所指向的地址的值

*/

func main() {
	// 声明普通变量
	var a int = 10
	fmt.Printf("a 变量的值:%d\n", a)    // 10
	fmt.Printf("a 变量的地址:%p\n", &a) // 0x

	// 声明 指针变量,指向a, 指针其实就是一个特殊的变量而已。,ptr命名  p
	// 定义变量格式  var ptr *类型
	var p *int
	p = &a // 指针变量赋值

	fmt.Printf("p 变量存储的指针地址:%p\n", p)         // a 的地址
	fmt.Printf("p 变量自己的地址:%p\n", &p)            // p 变量自己的地址
	fmt.Printf("p 变量存储的指针地址指向的值%d\n", *p) // a的值

	// 改变a的值   *p 和 a 其实是同一个地址
	a = 20
	fmt.Printf("a:%d\n", a)
	fmt.Printf("*p的值:%d\n", *p)

	// 通过指针改变a的值
	*p = 40
	fmt.Printf("a:%d\n", a)

	// 指针的套娃,指针指向指针 , 指针类型 第一个*指针类型, *int是这个指针对应的类型
	// 如何理解多个符号,第一个取出来后,后面就是它的类型 *(*(int))
	var ptr **int
	ptr = &p
	fmt.Printf("ptr指向的地址:%p\n", ptr)
	fmt.Printf("ptr的地址:%p\n", &ptr)
	fmt.Printf("*ptr变量存储的地址:%p\n", *ptr)
	fmt.Printf("**ptr存储的值:%d\n", **ptr)

	// 修改a的值
	**ptr = 100
	fmt.Println(a)
}

3、数组指针

数组指针:首先应该是一个指针,指向了一个数组

package main

import "fmt"

func main() {
	// 数组指针
	arr1 := [5]int{1, 2, 34, 5, 6}
	fmt.Println("arr1:", arr1)        //arr1: [1 2 34 5 6]
	fmt.Printf("arr1的地址:%p\n", &arr1) //arr1的地址:0xc00000e3c0

	// 创建一个指针,指向这个数组的地址,通过指针来操作数组
	var p1 *[5]int
	p1 = &arr1
	fmt.Printf("p1指向的地址%p\n", p1)
	fmt.Printf("p1自己的地址%p\n", &p1)
	fmt.Println("p1指向的地址的值:", *p1)

	// 操作指针控制数组
	// 指向了谁,这个指针就可以代表谁。
	// p1 = arr1
	(*p1)[0] = 100
	fmt.Println(arr1) // [100 2 34 5 6]
	fmt.Println(*p1)  // [100 2 34 5 6]

	p1[2] = 300       // 在程序中,我们更多时候是这样在使用指针的
	fmt.Println(arr1) // [100 2 300 5 6]
	fmt.Println(*p1)  // [100 2 300 5 6]
}

指针数组

package main

import "fmt"

func main() {
	a := 1
	b := 2
	c := 3
	d := 4

	// 创建一个指针数组
	arr1 := [4]*int{&a, &b, &c, &d}
	fmt.Println(arr1)

	fmt.Println(*arr1[0]) // 1
	fmt.Println(arr1[0])  // 0xc00001a0b8
	fmt.Println(&a)  // 0xc00001a0b8
	*arr1[0] = 100
	fmt.Println(a) // 100
}

4、指针函数

首先需要是一个函数,这个函数的返回值是一个指针。

package main

import "fmt"

func main() {
	ptr := f5()
	fmt.Println("ptr:", ptr)
	fmt.Printf("ptr类型:%T\n", ptr)
	fmt.Println("ptr的地址:\n", &ptr)
	fmt.Println("ptr地址中的值:\n", *ptr)
}

// 返回数组指针
func f5() *[4]int {
	arr := [4]int{1, 2, 3, 4}
	return &arr
}

5、指针作为函数参数

package main

import "fmt"

func main() {
   // 值传递
   a := 10
   fmt.Println("a:", a)  // 10
   fmt.Println("a addr:", &a) // 0xc00000e0a8

   f6(&a)

   fmt.Println("a:", a) // 20
   fmt.Println("a addr:", &a) // 0xc00000e0a8
}

// 指针当做函数的参数
func f6(ptr *int) {
   fmt.Println("ptr:", ptr)  // 0xc00000e0a8
   fmt.Println("ptr 指针的地址中的值", *ptr) // a = 10
   *ptr = 20 
}

补充:什么时候定义的变量会销毁,没有任何东西再指向它的时候,垃圾回收(GC)会回收。

【2】、结构体

变量:解决生活中问题(定义名字)

判断:解决生活中问题(分支:true false)

循环:解决生活中问题(循环:多次操作 for)

面向对象编程思维 OOP:将世界上的所有东西,抽象成一个个的类(属性、方法)

我想用一个变量来定义一个人的信息: map[string]string slice(,,,,,,)

人:属性(name、sex、age) 动作( 吃 eat() 工作 work() sleep() )

1、定义一个结构体

定义变量 var

定义结构体 type User struct {}

package main

import "fmt"

type User struct {
	name string
	age  int
	sex  string
}

func main() {
	// 通过结构体创建对象,以前的类型都是用的基本类型,自己定义类型了type,Struct
	// 定义了结构体对象,不赋值,默认都是这个结构体的零值 {"",0,""}
	var user1 User
	user1.name = "zhangsan"
	user1.sex = "girl"
	user1.age = 18
	fmt.Println(user1.name, user1.age, user1.sex)

	// 获取名字
	fmt.Println(user1.name)

	// 创建对象的方式二
	user2 := User{}
	user2.name = "aaa"
	user2.sex = "男"
	user2.age = 18
	fmt.Println(user2.name)

	// 创建对象的方式三
	user3 := User{
		name: "sss",
		age:  19,
		sex:  "男",
	}
	fmt.Println(user3)
	fmt.Println(user3.name)

	// 创建对象的方式四
	user4 := User{"ccc", 12, "男"}
	fmt.Println(user4)
	fmt.Println(user4.name)
}

2、结构体指针

package main

import (
	"fmt"
)

type User2 struct {
	name string
	age  int
	sex  string
}

func main() {
	user1 := User2{"qqq", 18, "男"}
	// 结构体类型    包.struct名
	fmt.Printf("%T,%p\n", user1, &user1) // main.User2,0xc00011e4b0
	// 结构体是值类型的
	user2 := user1
	fmt.Printf("%p,%p\n", &user1, &user2)
	fmt.Println("user2:", user2)
	user2.name = "hahaha"
	fmt.Println("user2:", user2)
	fmt.Println("user1:", user1)

	// 指针解决值传递的问题
	var ptr_user *User2
	ptr_user = &user1
	fmt.Printf("%T,%p\n", ptr_user, &ptr_user) // *main.User2,0xc0000ca020
	fmt.Println(*ptr_user)
	(*ptr_user).name = "ggg"
	fmt.Println(*ptr_user) // {ggg 18 男}
	fmt.Println(user1)     // {ggg 18 男}

	ptr_user.age = 13
	fmt.Println(user1) // {ggg 13 男}

	// 内置方法new 创建对象 new 关键字创建的对象,都返回指针,而不是结构体对象。
	user3 := new(User2)
	fmt.Println(user3) // &{ 0 }
	user3.name = "hhhh"
	fmt.Println(*user3) // {hhhh 0 }
	fmt.Println(user3)  // &{hhhh 0 }
	user3.age = 19
	user3.sex = "女"
	fmt.Println(user3)
	updateUser(user3)
	fmt.Println(*user3) // {hhhh 10000000000 女}
}

func updateUser(user *User2) {
	user.age = 10000000000
}

3、匿名结构体

package main

import "fmt"

type Student struct {
	name string
	age  int
}

func main() {
	// 匿名结构体
	s1 := Student{"jjj", 18}
	fmt.Println(s1.name, s1.age)
	// 匿名结构体,直接可以在函数内部创建出来,创建后就需要赋值使用
	s2 := struct {
		name string
		age  int
	}{
		name: "qqq",
		age:  9898,
	}
	fmt.Println(s2) // {qqq 9898}
	// 匿名字段
	t1 := Teacher{"qqq", 55}
	// 如何打印这个匿名字段,默认使用数据类型当做字段名称
	fmt.Println(t1.string, t1.int)
}

// 结构体中的匿名字段,没有名字的字段,这个时候属性类型不能重复
type Teacher struct {
	string
	int
}

4、结构体嵌套

package main

import "fmt"

type Person struct {
	name    string
	age     int
	address Address
}
type Address struct {
	city, state string
}

// 结构体是可以嵌套:我们就可以定义很多复杂的对象,来进行拼接了,构成一个更大的对象
func main() {
	// 一个结构体可能包含一个字段,而这个字段又是一个结构体:结构体嵌套
	var pre = Person{}
	pre.name = "ggg"
	pre.age = 66
	pre.address = Address{
		city:  "tianjin",
		state: "zh",
	}
	fmt.Println(pre)
	fmt.Println(pre.name)
	fmt.Println(pre.age)
	fmt.Println(pre.address.city)
	fmt.Println(pre.address.state)
}

5、结构体导出

public 公开的,所有地方都可以使用 、priavte私有的,只能自己使用

结构体:结构体名字,属性名字 。大写字母,可以导出使用,小写字母,不能导出使用。

如果结构体名称首字母小写,则结构体不会被导出。这时,即使结构体成员字段名首字母大写,也不会被导出。不能再其他包中只用

如果结构体名称首字母大写,则结构体可被导出,但只会导出大写首字母的成员字段,那些小写首字母的成员字段不会被导出。可以在其他包中使用

如果存在嵌套结构体,即使嵌套在内层的结构体名称首字母小写,外部也能访问到其中首字母大写的成员字段。

image-20241113145340627

标签:fmt,指针,地址,Println,main,ptr,结构
From: https://www.cnblogs.com/xuruizhao/p/18544838

相关文章

  • SS241113C. 数据结构 (struct)
    SS241113C.数据结构(struct)题意有\(n\)个数,\(m\)个操作,\(n,m,a_i\le10^6\),每次操作给区间\([l,r]\)的所有数字加\(1\),然后输出全局颜色数量,操作独立。思路感觉不好想,对我来讲有点难,需要更聪明的脑袋和丰富的想象力。首先\(O(n\sqrt{n})\)的莫队做法是显然的,假设......
  • PostgreSQL 创建相同结构的表
    我们经常会遇到这样的需求,就是我有一个表A,现在表A由于设计的时候存在一些缺陷,我现在需要创建一个相同结构的表B但是不需要表A的数据,只需要保持其原来的表设计即可。有啥快速的方法没有。下面我介绍下几种常见的方法和每种方法的缺点以及最好的方法。方法一:BEGIN;CREA......
  • 高性能日志结构化引擎 — GreptimeDB Piepline 设计与实现技术揭秘
    在GreptimeDBv0.9版本我们加入了对日志相关的支持:Pipeline引擎和全文索引。GreptimeDB致力于成为统一处理指标(Metric)、日志(Log)、事件(Event)和追踪(Trace)的时序数据库。在v0.9之前,用户虽然可以写入文本(string)类型的数据,但无法进行专门的解析和查询。有了Pipeline引擎和全文......
  • 数据结构——串的顺序存储实现
    概念:串(string):零个或多个任意字符组成的有限序列空串:(与空集合符号相同)子串:串中任意个连续字符组成的子序列称为该串的子串主串:包含子串的串相应地称为主串字符位置:字符在序列中的序号为该字符在串中的位置子串位置:子串第一个字符在主串中的位置空格串:由一个或多个空格组......
  • 教你如何清楚的分辨c语言各类指针类型定义
       可以这样说,学好了指针,就代表你学好了c语言。c语言中,通过合理的利用指针,可以快速高效的实现各种底层逻辑。下面陈列c语言中的各类指针定义,让大家分辨其中的具体意义。1,指针变量  我们定义一个指针变量p,指向整形变量i。#include<stdio.h>intmain(){int......
  • C语言的结构体
    结构体的基本概念和使用结构体(Struct)是一种用户自定义的数据类型,它允许将不同类型的数据项组合成一个单一的复合数据类型。结构体中的每个成员可以是不同的数据类型,包括基本数据类型、数组、指针,甚至是其他结构体。结构体的使用非常广泛,尤其在需要组织和管理复杂数据时尤为有......
  • C++函数传递引用或指针
    常见变量用法下面通过例子分别展示传递值、字符串、数组的用法示例代码#include<iostream>#include<string>//函数接受一个整数的引用和一个整数的指针voidmodifyValue(int&refValue,int*ptrValue){refValue=100;//通过引用修改值std::cout......
  • 指针加法中的隐形偏差:一次不该有的偏移踩坑
    在最近的开发中,有这样的一个需求,给一个结构体,我需要传出这个结构体的个别成员的地址,offsetof这个宏函数可以很好的解决这个业务需求,但是我还是踩坑了。下面看看我的踩坑记录。我们知道一个(TInfoRom*)infoRom类型的结构体指针,他指向当前结构体变量的首地址。我们可以通过off......
  • Linux CPU 拓扑结构之调度域 调度组 - 以8核ARM big.Little架构处理器为例
    CPU拓扑结构简介SMTLevel超线程处理器的一个核心MCLevel多核CPU的一个核心DIELevel一个物理CPU的晶片(注意不是package,package是封装好了的,肉眼看到的CPU处理器)(覆盖系统所有的CPU(CPU0~CPUN))cpu最小级别的就是超线程处理器的一个smt核,次小的一级就是一个多核cpu......
  • 电线、硬铜线和铜丝线是常见的电气连接和传导材料,它们在结构、用途、性能等方面有所不
    硬铜线与铜丝线的对比表格:特点硬铜线铜丝线材质纯铜(未经过退火处理)由多根细铜丝编织而成柔韧性较差,硬且不容易弯曲较好,具有较好的弯曲能力导电性良好,铜的导电性优异良好,铜的导电性优异抗拉强度高,适合高负载和长距离传输较低,柔性较好但抗拉强度差耐......