深入了解指针(1)

本文详细介绍了C语言中指针的概念,包括指针作为内存地址的访问工具,指针变量的定义、类型和大小,以及const修饰符的应用。同时探讨了void*指针、野指针的产生原因和处理,以及传值调用与传址调用的区别。

内存与地址

学习指针,我们首先要了解指针,指针是用来访问内存的。举个例子,就像过节走亲访友,首先我们要知道地址,才可以去拜访。那么指针的作用就是地址,用于以后可以轻松的访问到内存。也可以这么理解:内存的单元编号==地址==指针。

指针变量与地址

&,在C语言中,名为取地址的操作符,例如:

int main()
{
    int a=0;
    printf("%p",&a);
    return 0;
}

这样便可以得到a的地址。

得到的地址p也是一个变量,其中存放的是a的地址。那我们该如何定义这种变量呢?

指针类型

定义指针首先要了解指针的类型,有int型,有char型,还有float型......

其次我们还要知道一个解引用的操作符(*)

//整型
int a=20;
int*p=&a;

指针变量的大小

有地址总线决定,我们知道,计算机有32位也有64位,所以指针的大小也有两种,四个字节和八个字节,其中32位有32个比特位,也就是4个字节,64位则是8个字节。而且指针的大小与前面说的指针的类型不同,指针的大小只和平台有关,与指针的类型无关。

指针类型的意义

指针的类型决定了对指针解引用时的权限大小(一次可以操作几个字符)

例如;char*的指针只能访问一个字节,int*的指针可以访问四个字节。

指针+-整数

上面我们说了char*与int*的区别,所以他们+-一个整数的结果也是不一样的。

char*类型的指针+1跳过一个字节,而int*类型的指针+1跳过4个字节。

所以结论:指针类型决定了指针向前或者向后走一步的距离大小。

void*指针

上面介绍的指针在定义时我们知道其类型,而如果我们并不知道的话,便可以用void*指针,

void*指针可以理解为无具体类型的指针(泛型指针)可以接受任何类型的地址,但是这类指针并不可以直接进行+-整数的操作,也不可以进行解引用的操作。所以我们一般使用在函数参数的部分,用来接收不同类型数据的地址,实现泛型编程的效果。

const修饰指针

const修饰变量

通过使用const修饰,可以使一个变量具有常属性,但本质上还是变量(在c++中const修饰后变量会变成常量)具有常属性之后,这个变量变得不可被修改,但是通过指针我们依旧可以改变存在一个变量里面的值,如:

可以看出n的值改变了,这是不符合const限制的,所以是不合理的,那么如何让指针也无法改变const定义后的变量的值呢?

const修饰指针变量

如果const放在*左边修饰的是指针内容,指针内容就不会发生改变。但是指针变量本身可以改变。

运行后我们可以发现,n所指的值还是10,即所存的数值没有改变。但是p的指向改变了。

int main()
{
    int n=10;
    int m=20;
    int const * p=&n;
    *p=20;
    p=&m
}

相反的,如果放在*右边的话,p中所存放的值会发生改变,而p的指向并不会发生改变,*p不变。

如果*前后都有const限制的话,那么两个值都不会发生改变。

指针运算

分为三种:指针+-整数;指针-指针;指针的关系运算(指针比较大小)。

注意:指针-指针的运算方式的两个指针指向同一块空间。

野指针

概念:就是指针指向的位置是不可知的(随机的,不正确的,没有限制的)

产生野指针的原因

1.指针未初始化

int main()
{
    int * p;//局部变量未初始化,默认为随机值
    *p=20;
return 0;
}

2.指针的越界访问

如出现在数组当中,超出数组的大小。

3.指针指向的空间释放

不能返回局部变量的地址。

assert断言

assert()括号内只要是表达式都可以,如果表达式的结果为假,assert()就会报错,使程序的执行中止。可以用来判断一个指针是否是一个空指针。

#include<assert.h>

是他的头文件。

传值调用和传址调用

传址调用,可以让函数和主调函数(不是主函数,是自己创建的函数)之间建立真正的联系,,在函数内部可以修改主调函数中的变量;所以未来函数中只是需要主调函数的变量值来实现计算,就可以采用传值调用(人话:只用不改变)如果函数内部要修改主调函数中变量的值,就需要传址调用。

结语:关于指针的学习并没有结束,后续还会有更多关于指针的介绍。

内容概要:本文详细介绍了一个基于Java和Vue的联邦学习隐私保护推荐系统的设计与实现。系统采用联邦学习架构,使用户数据在本地完成模型训练,仅上传加密后的模型参数或梯度,通过中心服务器进行联邦平均聚合,从而实现数据隐私保护与协同建模的双重目标。项目涵盖完整的系统架构设计,包括本地模型训练、中心参数聚合、安全通信、前后端解耦、推荐算法插件化等模块,并结合差分隐私与同态加密等技术强化安全性。同时,系统通过Vue前端实现用户行为采集与个性化推荐展示,Java后端支撑高并发服务与日志处理,形成“本地训练—参数上传—全局聚合—模型下发—个性化微调”的完整闭环。文中还提供了关键模块的代码示例,如特征提取、模型聚合、加密上传等,增强了项目的可实施性与工程参考价值。 适合人群:具备一定Java和Vue开发基础,熟悉Spring Boot、RESTful API、分布式系统或机器学习相关技术,从事推荐系统、隐私计算或全栈开发方向的研发人员。 使用场景及目标:①学习联邦学习在推荐系统中的工程落地方法;②掌握隐私保护机制(如加密传输、差分隐私)与模型聚合技术的集成;③构建高安全、可扩展的分布式推荐系统原型;④实现前后端协同的个性化推荐闭环系统。 阅读建议:建议结合代码示例深入理解联邦学习流程,重点关注本地训练与全局聚合的协同逻辑,同时可基于项目架构进行算法替换与功能扩展,适用于科研验证与工业级系统原型开发。
源码来自:https://pan.quark.cn/s/a4b39357ea24 遗传算法 - 简书 遗传算法的理论是根据达尔文进化论而设计出来的算法: 人类是朝着好的方向(最优解)进化,进化过程中,会自动选择优良基因,淘汰劣等基因。 遗传算法(英语:genetic algorithm (GA) )是计算数学中用于解决最佳化的搜索算法,是进化算法的一种。 进化算法最初是借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传、突变、自然选择、杂交等。 搜索算法的共同特征为: 首先组成一组候选解 依据某些适应性条件测算这些候选解的适应度 根据适应度保留某些候选解,放弃其他候选解 对保留的候选解进行某些操作,生成新的候选解 遗传算法流程 遗传算法的一般步骤 my_fitness函数 评估每条染色体所对应个体的适应度 升序排列适应度评估值,选出 前 parent_number 个 个体作为 待选 parent 种群(适应度函数的值越小越好) 从 待选 parent 种群 中随机选择 2 个个体作为父方和母方。 抽取父母双方的染色体,进行交叉,产生 2 个子代。 (交叉概率) 对子代(parent + 生成的 child)的染色体进行变异。 (变异概率) 重复3,4,5步骤,直到新种群(parentnumber + childnumber)的产生。 循环以上步骤直至找到满意的解。 名词解释 交叉概率:两个个体进行交配的概率。 例如,交配概率为0.8,则80%的“夫妻”会生育后代。 变异概率:所有的基因中发生变异的占总体的比例。 GA函数 适应度函数 适应度函数由解决的问题决定。 举一个平方和的例子。 简单的平方和问题 求函数的最小值,其中每个变量的取值区间都是 [-1, ...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值