指针 结构体 const 小结

指针

首先:
指针是什么?
1. 指针是内存中一个最小单元的编号,也就是地址
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量

指针变量
我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个
变量就是指针变量
eg:int a = 2; int *p = &a 那么p就是一个整形指针变量
稍后再详细讨论指针变量的类型。
指针的大小是多少?
不确定的 有的时候是四个字节 有的时候是八个字节 为啥?
因为指针变量是用来存放地址的 而经过仔细的计算和权衡我们发现一个比特位给一个对应的地址是比较合适的,所以在32位机器下对应32跟地址线,同时每个地址线会产生高电压低电压也就是0和1
所以
1,在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。

2.那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址
**注意:**指针变量的大小与指针的类型无关 只跟属于的机器位数是32位的还是64位的

指针类型在我看来其实就是跟数字类型差不多 就是在后面加了一个解引用符

  • int * 整形指针 char * 字符型指针 float * 浮点型指针 等等
    为什么要区分不同的指针类型呢?
    关键在于不同的指针类型可以在内存中访问不同大小的内存
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++,p++) printf("%d ", *p);
	printf("\n");
	char* st = arr;
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++,st++) 
		printf("%d ", *st);

	return 0;
}

arr数组在内存中的表述
上述是arr数组在内存中的二进制表示 我们可以看出,当指针类型是int 时候
p+1 访问的是4个字节 但是当指针类型是char 的时候 st+1 访问的 只能是一个类型 因此 都是循环十次 但是打印的却完全不同!
再次强调,不同的指针类型在加减的时候访问的内存大小是不同的!

野指针
补充一个野指针小知识
首先野指针是如何产生的?

  1. 指针未初始化
    eg:int *p//这边指针p未定义,所以是默认值
  2. 指针越界访问
    eg int arr[10] = { 0 }; int* p = arr;//表示指向p指向的是数组的首地址 for (int i = 0; i <= sizeof(arr) / sizeof(arr[0]); i++) *(p++) = i;//因为数组的大小最多就是第十位,但是这边的*p最终指向的是第十一位
    3 指针指向的空间释放
int* p = (int*)malloc(sizeof(int) * 10);
	free(p);
    //p = NULL
    //如果不加上p = NULL那么当free释放内存后P就变成了野指针

所以应养成良好的编程习惯 在每次释放动态内存时 都应该加上将那个释放的地址 设为空指针。
野指针在内存中就好比是一个不定时的炸弹 不知道什么时候就爆炸了 我们应该避免它
方法
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性

结构体

老问题:啥是结构体?
我们在之前已经学习了整形,浮点型,字符型等等
但是要知道生活中有许多事物不止一种类型的
eg:一本书 作者 零售价 发布日期
这三种属性分别用 字符串 浮点数 整数表示 因为这三者都属于同一本书
所以他们是不可分割的一部分,所以便可引出结构体——

struct book
{ 
	char name[20];//作者
	float price;//售价
	int year;//发布年份
	
};

上述结构体中的”作者 售价 发布年份“都可以称作结构体成员.
结构的成员可以是标量、数组、指针,甚至是其他结构体。

结构体变量的定义和初始化
在我看来 其实和整形 浮点型什么的都大同小异

`struct Point
{
 int x;
 int y; }p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = {x, y};`

访问结构体成员一共就两种方式
1,如果是结构体变量 那么用 点 . 操作符
2. 如果时结构体指针 那么用 ->

void print(struct Stu* ps) {
 printf("name = %s   age = %d\n", (*ps).name, (*ps).age);
    //使用结构体指针访问指向对象的成员
 printf("name = %s   age = %d\n", ps->name, ps->age);
}
int main()

最后一个问题:
结构体传参有两种

struct S {
	int data[1000];
	int num;
};
void print1(struct S s);
void print2(struct S* ps);

选择第二种 至于为啥 问就是 1会压栈
因为结构体过大 参数压栈系统开销过大 会导致性能下降

const

很多同学写算法题目前面都写一个 const int N = 100010;l
为什么呢?
简单概括一下 const 修饰的值可以被计算机当作是一个常量 所以一旦被他修饰就很安全 不会担心上面出现变化
上代码

void test1()
{
    int n = 10;
    int m = 20;
    int *p = &n;
    *p = 20;//ok?这个时候是可以的,不会报错
    p = &m; //ok?同上 都没有const修饰
}
void test2()
{
     //代码2
    int n = 10;
    int m = 20;
    const int* p = &n;
    *p = 20;//ok?会报错 这个时候const 修饰的是(*p)这个时候不能修改
    p = &m; //ok? 可以const没有修饰p
}
void test3()
{
    int n = 10;
    int m = 20;
    int *const p = &n;
    *p = 20; //ok?可以修改 const修饰的是p与*p无关
    p = &m;  //ok?不可以
    
    }
 void test4()
{
    int m = 10;
    int n = 20;
    const int *const p = &m;
    *p = 20// 恭喜你 都不可以 因为这个时候const两个都修饰了
    p = &n;// 同上!!!

总结:
*const修饰指针变量的时候:

  1. const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改
    变。但是指针变量本身的内容可变。
  2. const如果放在的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指
    针指向的内容,可以通过指针改变。
    **

以上是个人的一些拙见 当作笔记来复习的 要是有什么不足的地方还望各位补充!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要将一个指针结构体赋值给另一个指针结构体,可以通过以下步骤进行: 1. 创建新的目标结构体指针。 2. 使用解引用运算符 `*`,将源结构体指针所指向的实际结构体复制到目标结构体中。 3. 如果结构体中包含动态分配的内存(如字符串指针等),需要进行适当的内存分配和复制。 以下是一个示例代码,假设有两个结构体类型为 `MyStruct` 的指针 `src` 和 `dest`: ```c #include <stdlib.h> #include <string.h> typedef struct { int value; char* text; } MyStruct; void copyStruct(MyStruct* dest, const MyStruct* src) { // 复制结构体中的基本数据类型成员 dest->value = src->value; // 复制结构体中的字符串指针成员 dest->text = malloc(strlen(src->text) + 1); strcpy(dest->text, src->text); } int main() { MyStruct* src = malloc(sizeof(MyStruct)); src->value = 123; src->text = strdup("Hello World"); MyStruct* dest = malloc(sizeof(MyStruct)); // 将源结构体指针赋值给目标结构体指针 copyStruct(dest, src); // 打印目标结构体中的数据 printf("Value: %d\n", dest->value); printf("Text: %s\n", dest->text); // 释放内存 free(src->text); free(src); free(dest->text); free(dest); return 0; } ``` 在上述示例代码中,我们定义了一个结构体类型为 `MyStruct`,其中包含一个整数成员 `value` 和一个字符串指针成员 `text`。 在 `copyStruct` 函数中,我们通过使用动态内存分配函数 `malloc` 来分配目标结构体中的字符串指针的内存,并使用 `strcpy` 函数将源结构体中的字符串复制到目标结构体中。 在 `main` 函数中,我们创建了源结构体指针 `src` 和目标结构体指针 `dest`,并通过调用 `copyStruct` 函数将源结构体赋值给目标结构体。 最后,记得释放动态分配的内存,以避免内存泄漏。 希望这个示例能对你有所帮助。如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天少点debug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值