c语言修炼秘籍【第五章】指针

LVGL v8.3 图片显示与解码缓存实战:PNG 上屏、C 数组与文件双方案 LVGL v8.3 图片两种存储方式、PNG/JPG 上屏解码器挂载、LV_IMG_CACHE_DEF_SIZE 缓存调优、手动预解码头像有效性判断,及"缓存被动画清空"真实踩坑。 阅读详情

c语言修炼秘籍【第五章】指针

【心法】
【第零章】c语言概述
【第一章】分支与循环语句
【第二章】函数
【第三章】数组
【第四章】操作符
【第五章】指针
【第六章】结构体
【第七章】const与c语言中一些错误代码
【禁忌秘术】
【第一式】数据的存储
【第二式】指针
【第三式】字符函数和字符串函数
【第四式】自定义类型详解(结构体、枚举、联合)
【第五式】动态内存管理
【第六式】文件操作
【第七式】程序的编译



前言

本文会从介绍指针是什么开始,循序渐进地介绍指针的使用、指针使用时会遇到的问题、指针能进行哪些运算、指针与数组之间的关系,以及指针数组这些内容。


一、指针是什么?

指针是什么?
指针理解的2个要点:

  1. 指针是内存中一个最小单元的编号,也就是地址。
  2. 平时说的指针,通常指的是指针变量,是用来存放地址的变量。

指针就是地址,口语中说的指针是指针变量


内存:
在这里插入图片描述
指针变量:
通过取地址操作符&取出变量的内存起始地址,把地址放入一个变量中,这个存放地址的变量我们就称其为指针变量。

int main()
{
	int a = 10; // 在内存中开辟一片空间
	int* pa = &a; // 使用 &取出变量 a的地址,将该地址赋值给变量 pa
				  // 变量 a在内存中占据 4个字节的空间,&操作符将这 4个字节的起始字节的地址存放在 pa中
				  // pa就是一个指针变量

	return 0;
}

总结:指针变量就是用来存储地址的变量。(存放在指针变量中的值都被当作地址来处理)
一个变量是需要存储在内存中的,那么问题来了,一个地址需要多大的内存空间来存储呢?换言之,一个指针变量所占的内存空间是多大呢?
对于32位的机器,可以产生232个地址,也就需要32个二进制位来存储,所以32位机器中的地址大小为4字节;
对于64位的机器,可以产生264个地址,也就需要64个二进制位来存储,所以64位机器中的地址大小为8字节;

这时又会产生新的疑问,一个地址表示的内存空间又是多大呢? - - 1个字节。
原理可以参考https://www.zhihu.com/question/421675295

一个地址能表示1个字节,32位机器能表示的地址空间大小为4GB,这很显然对于我们现在使用的计算机而言是不够用的;一台64位机器的编址范围是多大呢?要知道240就已经是1TB了,264个地址是可预见的用不完的。

总结

  • 指针是用来存放地址的,地址是唯一标识一块地址空间的。
  • 指针大小在32位平台是4个字节,在64位平台是8个字节。

二、指针和指针类型

我们都知道,变量是有类型的,char类型、int类型、float类型等等,那么指针变量有没有类型呢?

看下面的代码

int a = 10;
p = &a;

要把a的地址存放在p中,这里的p应该是什么类型的指针变量呢?

下面是不同类型的指针变量

#include <stdio.h>

int main()
{
	char *pc = NULL;
	short *ps = NULL;
	int *pi = NULL;
	long *pl = NULL;
	float *pf = NULL;
	double *pd = NULL;

	return 0;
}

// 指针变量的定义方式是:
// type +*
// type表示指针指向数据的类型,*表示该变量是一个指针

char *类型就是存放char类型变量的指针;
int *类型就是存放int类型变量的指针;
…
等等。
那指针类型的有什么意义呢?请接着往下看。

1.指针 + - 整数

看代码

#include <stdio.h>

int main()
{
	int num = 10;
	char *pc = &num;
	int *pi = &num;

	printf("&num == %p\n", &num);
	printf("pc == %p\n", pc);
	printf("pc + 1 == %p\n", pc + 1);
	printf("pi == %p\n", pi);
	printf("pi + 1 == %p\n", pi + 1);

	return 0;
}

运行结果:
在这里插入图片描述
大家发现了有什么规律吗?
char类型在内存中占1个字节,char类型的指针+1,地址往后移动了一个字节。
int类型在内存中占4个字节,int类型的指针+1,地址往后移动了4个字节。
可以发现,指针的类型是决定了指针向前或向后走的步长。

2.指针的解引用

看代码,调试时观察pc和pi指向的内存空间中值的变化。

#include <stdio.h>

int main()
{
	int num = 0x11223344;
	char* pc = &num;
	int* pi = &num;

	*pc = 0;
	*pi = 0;

	return 0;
}

在这里插入图片描述

在这里插入图片描述
可以看到,虽然pc和pi的地址相同,但使用它们对num进行修改时,能够修改的范围并不相同,
pc只能修改一个字节,pi可以修改4个字节。

总结
指针的类型决定了,对指针解引用的时候有多大权限(能操作几个字节)
比如:char类型的指针,只能操作一个字节,int类型的指针能操作4个字节。

三、野指针

什么是野指针?
野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

1.野指针的成因

  1. 指针未初始化
int main()
{
	int* p; // 局部指针变量,未初始化,默认为随机值,此时 p指针是野指针
	*p = 20; 

	return 0;
}
  1. 指针越界访问
int main()
{
	int arr[10] = { 0 };
	int* pa = arr;

	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		*(pa + i) = i; // 当指针指向的范围超出数组arr的范围时,pa就是野指针
	}

	return 0;
}

这里要注意,不要写成*pa+i = i,原因如下:

#include <stdio.h>

int main()
{
	int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
	int* pa = arr;

	printf("%d\n", *pa + 3); // 这里会输出什么
	printf("%d\n", *(pa + 3)); // 这里会输出什么

	return 0;
}

运行结果:
在这里插入图片描述
这是因为操作符*的优先级比+的更高,
*pa + 3相当于,对pa地址解引用之后再+3;
*(pa + 3)才是先对指针+3再解引用。

  1. 指针释放的空间释放
在这里插入代码片#include <stdlib.h>

int main()
{
	int *p = (int*)malloc(10 * sizeof(int)); // 动态分配10个int类型大小的空间给指针p
	*p = 10;
	free(p); // 将malloc分配给p的空间释放
	*p = 20; // 使用释放后的空间,此时p为野指针

	return 0;
}

这里使用到了动态内存分配,后续章节会详细介绍。

2.如何规避野指针

  1. 定义指针是进行初始化
  2. 小心指针越界,使用指针时检查边界
  3. 指针指向空间释放后置空
  4. 避免返回局部变量的地址
  5. 指针使用前检查有效性
#include <stdio.h>
#include <stdlib.h>

int main()
{
	int *p = NULL; // 将指针初始化为NULL,此时仍然不能使用
	*p = 20; // error,错误代码
	// 可改为,指针使用之前检查其有效性
	if (p != NULL)
	{
		*p = 20;
	}
	int a = 10;
	p = &a; // 此时指针p有了确定的值,才可以使用

	// c语言本身是不会检查数组的越界行为的,当使用指针访问数组时,需要程序员自己检查指针的行为是否越界

	// 动态分配的空间在释放后手动置空
	int* pf = (int*)malloc(10 * sizeof(int));

	//.. 使用代码

	free(pf); // 释放pf的空间
	pf = NULL; // 手动将pf指向空指针

	// 局部变量的地址
	char *pc = NULL;
	{
		char ch = 'a';
		pc = &ch;
	}
	*pc = 'b'; // error,这里使用了局部变量ch的地址,但ch的空间已经销毁,pc变成了一个野指针

	return 0;
}

这些内容会在后续的指针详解中介绍。

四、指针运算

1.指针 + - 整数

#include <stdio.h>

#define N_VALUES 5

int main()
{
	float values[N_VALUES];
	float *pf = NULL;
	// 对 values数组进行初始化
	// 使用了指针+整数和指针关系运算
	for (pf = values; pf < &values[N_VALUES]; pf++)
	{
		*pf = 0;
	}

	return 0;
}

指针 + - 整数表示,指针向后或向前移动整数个类型的空间

2.指针 + - 指针

int my_strlen(char* str)
{
	char* pstr = str;
	while (*pstr)
	{
		pstr++;
	}
	return pstr - str; 
}

指针 - 指针 得到两指针之间元素的个数。
注:只有类型相同的指针才能进行该运算,且两个指针必须指向同一块空间

错误示例

#include <stdio.h>

int main()
{
	int a = 10;
	int b = 20;
	int *pa = &a;
	int *pb = &b;

	char c = 'a';
	char *pc = &c;

	printf("pb - pa == %d\n", pb - pa);
	printf("pc - pa == %d\n", pc - pa);
	printf("pc - pb == %d\n", pc - pb);

	return 0;
}

这样的代码没有任何意义

3.指针的关系运算

#include <stdio.h>

#define N_VALUES 5

int main()
{
	float values[N_VALUES];
	float *pf = NULL;
	// 代码一
	for (pf = values; pf <= &values[N_VALUES]; pf++)
	{
		*pf = 0;
	}

	// 代码二
	for (pf = &values[N_VALUES]; pf >= values; pf--)
	{
		*pf = 0;
	}

	return 0;
}

上面的两个代码逻辑上实现的效果相同,但是建议使用第一种,第二种与数组的前一个元素比较的行为是c语言未定义的。不同编译器。

标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但是不允许与指向第一个元素前面的那个内存位置的指针进行比较

五、指针和数组

看一个例子

#include <stdio.h>

int main()
{
	int arr[10] = { 0 };
	printf("arr == %p\n", arr);
	printf("&arr[0] == %p\n", &arr[0]);

	return 0;
}

运行结果:
在这里插入图片描述
可以看到数组名和首元素地址是相同的。

总结
数组名表示首元素地址。有两种特例,具体请看【第三章】数组
所以下面的代码是可行的

#include <stdio.h>

int main()
{
	int arr[10] = { 0 };
	int *pf = arr; // 将数组名当作地址放入一个指针中,我们使用的指针来访问一个数组就成为了可能

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("&arr[%d] == %p <==> pf + %d == %p\n", i, &arr[i], i, pf + i); // 比较指针是否与数组元素的地址相等
	}
	
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		*(pf+i) = i; // 使用指针来对数组进行初始化
		printf("arr[%d] == %d, *(pf+%d) == %d\n", i, arr[i], i, *(pf+i));
	}

	return 0;
}

运行结果:
在这里插入图片描述

六、二级指针

指针变量也是变量,是变量就有地址,那么,指针的地址存放在哪呢?
存放在二级指针中

int main()
{
	int a = 10;
	int *pa = &a;
	int **ppa = &pa;

	return 0;
}

在这里插入图片描述
在这里插入图片描述
二级指针的运算:

  • *ppa访问的实际是pa。使用操作符*对ppa解引用,得到的是pa的地址。
int b = 20;
*ppa = &b; // 等价于pa = &b
  • **ppa访问的实际是a。使用操作符*对*ppa解引用,等价于*pa。
**ppa = 40; // 等价于*pa = 40

注意,二级指针并不能用来表示二维数组
二维数组在内存空间中地址是连续的,而二级指针并不是。

看例子

#include <stdio.h>

int main()
{
	int arr[3][3] = { 0 };

	int **parr = arr;

	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			parr[i][j] = 3 * i + j;
		}
	}

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			printf("%d ", parr[i][j]);
		}
	}

	return 0;
}

在这里插入图片描述
从内存空间上来分析:
在这里插入图片描述
在这里插入图片描述
那么我们要怎么利用指针来访问二维数组呢?
使用数组指针,指针数组不行

示例代码

#include <stdio.h>

int main()
{
	int arr[3][3] = { 0 };
	int (*pa)[3] = arr;

	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			pa[i][j] = 3 * i + j;
		}
	}

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			printf("%d ", pa[i][j]);
		}
		printf("\n");
	}

	return 0;
}

运行结果:
在这里插入图片描述
这里对其进行简单的分析,关于数组指针还会在后续章节中进行详细介绍。
二维数组中的元素是一个一维数组,上述代码中,该一维数组的类型为int [3],所以二维数组名代表的首元素地址其实是这个一维数组的地址,要用一个类型为int [3]的指针变量来接收,也就是int (*pa)[3]。- - []中的3必须有。
而指针数组,不可行的原因也是因为类型不匹配的缘故。

但如果你非要用二级指针来访问二维数组也不是不行

看代码:

#include <stdio.h>

void print1(int* nums, int numsSize, int numsColSize)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < numsSize / numsColSize; i++)
	{
		for (j = 0; j < numsColSize; j++)
		{
			printf("%d ", *(nums + i * numsColSize + j));
		}
		printf("\n");
	}
}

void print2(int* nums, int numsSize, int numsColSize)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < numsSize / numsColSize; i++)
	{
		for (j = 0; j < numsColSize; j++)
		{
			printf("%d ", nums[i][j]);
		}
		printf("\n");
	}
}

int main()
{
	int nums[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
	int numsColSize = sizeof(nums[0]) / sizeof(nums[0][0]);
	int numsSize = (sizeof(nums) / sizeof(nums[0])) * numsColSize;

	print1(nums, numsSize, numsColSize);
	print2(nums, numsSize, numsColSize);

	return 0;
}

这段代码中的print1函数是能够正确输出二维数组的值的。
这样的操作是建立在我们知道二维数组在内存中的空间是连续分布的基础上来实现的,所以c语言中各种数据类型它们在内存中是以什么形式存储的是非常重要的,这部分会在后续的进阶攻略中详细介绍。

七、指针数组

指针数组,顾名思义,它是一个数组,数组中的元素是指针。

int *pa[3]; - - 这就是一个指针数组,这个数组有3个元素,每个元素的类型为int *
在这里插入图片描述


总结

本文对c语言中使用的指针进行了较简略的介绍,包括什么是指针,指针类型有什么用,指针的一些运算,什么是野指针,如何利用指针访问数组,二级指针使用中会出现的问题,以及指针数组。

YOLO26算法大门区域检测+训练好的模型+285张数据集+pyqt可视化界面.zip 附训练好的 YOLO 权重与 PyQt 可视化检测界面,页面底部含可视化效果预览,毕设/课设开箱即用。 【数据集概况】 · 检测类别(中文):[大门(gates)] 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 64 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.6364** mAP50-95 | 0.4539 Precision | 0.7309 Recall | 0.6111 train/box_loss | 0.6662 train/cls_loss | 0.5916 val/box_loss | 1.3351 val/cls_loss | 1.5479 【训练过程分析】 训练过程可分成三个主要阶段:前期、中期和后期。刚开始时,模型的损失函数确实有了显著下降,box_loss 从0.6662开始,经过几轮的迭代,迅速降至0.5左右。但到了中期,loss 的下降速度明显放缓,甚至有停滞不前的趋势。这一现象在val/box_loss的表现上尤其明显,从1.3351缓慢上升至1.4左右,直到训练到64轮时才略有下降。在这一阶段,mAP50从0.6364仅轻微上升到0.64,提升有限。这期间,模型似乎陷入了平台期,进展缓慢,让人感到有些煎熬。从第30轮到第64轮,我频繁查看曲线图,希望能捕捉到一点改善的迹象,但都未能如愿。这个阶段也让我对模型的潜力产生了怀疑,担心训练过程可能需要更长时间才能看到显著改善。 进入后期阶段,尽管损失函数略有下降,但mAP50的提升并不明显,这让人感到非常... 使用场景:毕业设计、课程设计、深度学习入门、工业场景落地验证。 立即下载

相关推荐

状态估计【卡尔曼滤波kalman】UKF、EKF、粒子滤波PF学习与研究(Matlab代码实现)

内容概要:本文围绕非线性状态估计中的三种经典滤波算法——无迹卡尔曼滤波(UKF)、扩展卡尔曼滤波(EKF)和粒子滤波(PF)展开系统性学习与研究,重点在于通过Matlab编程实现这些算法的核心流程,并将其应用于实际系统的状态估计问题中。文档不仅详细阐述了各算法的数学原理、适用条件与性能差异,还提供了完整的仿真代码与案例分析,帮助读者深入理解其在非线性、非高斯环境下的表现特性。同时,资源拓展至EKF与神经网络融合训练、多源数据融合等高级应用场景,展现了其在智能控制、无人机导航、电力系统状态估计、目标跟踪等领域的广泛应用价值。; 适合人群:具备一定信号处理、控制理论或状态估计基础的研究生、科研人员及工程技术人员,尤其适用于从事自动化、机器人、导航、电力电子与智能系统等相关方向的研究与开发工作者;; 使用场景及目标:① 掌握UKF、EKF与PF在非线性系统中的建模思路与Matlab实现方法,理解其优缺点与适用边界;② 提升科研仿真能力,能够独立构建状态估计模型并进行算法对比验证;③ 将所学方法应用于如电池SOC估算、无人机姿态估计、传感器融合、故障诊断等实际工程问题中;; 阅读建议:建议结合Matlab动手实践,逐行解读并调试所提供的代码,深入理解算法实现细节;同时可延伸学习文中提及的数据融合、神经网络与滤波器结合等进阶主题,以构建完整的状态估计技术知识体系。

C语言修炼秘籍【第零章】c语言概述

c语言是一门编程语言。语言的作用就是交流,人们可以利用它与计算机进行交流,让计算机知道你需要它完成什么工作。本系列文章是对笔者在c语言学习的总结记录。本文会先粗略的介绍c语言中需要学习的内容。

PLKDTHFS的博客 1664

Plecs全桥LLC谐振变换器仿真模型

内容概要:本文档系统性地整合了电力电子与控制系统仿真领域的丰富资源,聚焦于基于Plecs和Simulink平台的高频软开关变换器建模与仿真,涵盖全桥LLC、双向CLLC、DAB、PFC、Vienna整流器、Buck-Boost等多种典型拓扑结构。资源内容不仅包括闭环控制(如变频控制、移相混合控制、双闭环、恒压恒流双竞争控制)的仿真模型,还配套提供详细的参数设计报告、Mathcad计算书、PPT说明文档及参考文献,构建了从理论建模到工程实现的完整技术链条。此外,文档拓展至状态估计(如卡尔曼滤波、EKF、UKF、PF)与智能算法(如BP神经网络、模型预测控制)在电力系统中的融合应用,为先进控制策略的研究与复现提供了坚实支撑。; 适合人群:面向具备电力电子、自动控制或电气工程等相关专业背景,熟练掌握MATLAB/Simulink/Plecs等仿真工具,从事高频开关电源、新能源变换系统、储能系统或车载电源研发的研究生、高校科研人员及企业工程技术人员。; 使用场景及目标:① 学习并掌握全桥LLC等谐振变换器的核心工作原理与闭环控制系统设计方法,特别是变频与移相控制策略的实现细节;② 利用提供的仿真模型与Mathcad计算工具,快速完成实际项目中的参数设计、性能验证与优化迭代;③ 结合状态估计算法与神经网络等智能方法,开展电力电子系统状态观测、故障诊断或控制策略创新等前沿科研课题的复现与探索。; 阅读建议:建议严格按照资源目录结构循序渐进地查阅,优先下载并运行核心仿真模型,结合对应的设计报告与计算书深入理解其建模逻辑与参数推导过程,重点关注闭环控制架构、软启动策略及中点电位平衡等关键技术环节,并可进一步将状态估计与智能算法模块融入现有模型,探索其在系统优化中的应用潜力。

c语言修炼秘籍【第二章】函数

本文会从函数是什么开始,逐一介绍函数的语法结构,如何声明和定义一个函数,函数的参数类型,调用函数时的传参类型,函数的调用方式,函数递归,并在最后对汉诺塔、青蛙跳台阶和八皇后问题进行详细分析(包含全部代码)

PLKDTHFS的博客 1443

线性代数知识点整理

线性代数基础知识点摘要整理

cuguanren的博客 3万+

1006. 换个格式输出整数 (15)-PAT乙级真题

1006. 换个格式输出整数 (15)让我们用字母B来表示“百”、字母S表示“十”,用“12…n”来表示个位数字n(&lt;10),换个格式来输出任一个不超过3位的正整数。例如234应该被输出为BBSSS1234,因为它有2个“百”、3个“十”、以及个位的4。输入格式:每个测试输入包含1个测试用例,给出正整数n(&lt;1000)。输出格式:每个测试用例的输出占一行,用规定的格式输出n。输入样例1...

柳婼 の blog 2243

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第二式】指针

字符指针数组指针指针数组数组传参和指针传参几种数组、指针之间的比较函数指针函数指针数组指向函数指针数组的指针回调函数指针和数组的笔试题指针是一个存储地址的变量,地址是一块内存空间的唯一标识;指针的大小是固定的(4字节或8字节);指针是有类型的,它的类型决定它 + - 整数时移动的步长、*解引用操作时的权限;指针是能够进行运算的,+ - 整数、指针相减、指针的关系运算;接下来,就让我们继续探讨指针的进阶主题。对于普通的指针,我们都已经很熟悉了。

PLKDTHFS的博客 1518

python-snap7 报错:can‘t find snap7 library. If installed, try running ldconfig

1、使用场景: Python 读取西门子 S7 系列 PLC 信息,会用到 snap7 库,网上也有很多案例。但是,运行时会报错:can't find snap7 library. If installed, try running ldconfig 2、解决方案: A、下载项目需要依赖的 dll、lib 文件: i、Sourceforge下载:https://sourceforge.net/projects/snap7/files/ ii、优快云下载(免费):https://dow.

蜡笔小新历险记的博客 3648

c语言修炼秘籍【第三章】数组

本文将会介绍常用到的一维数组和二维数组是如何使用及它们在内存中是如何存储,说明何为数组越界,并讨论数组在作为函数参数时应该如何使用。在最后附带三子棋和扫雷的代码实现详解。本文对一维和二维数组的初始化、创建、使用,作出的简要的介绍,并通过冒泡排序算法的实现,详细说明了当数组作为函数参数时的性质 - - 传递的是首元素地址。在最后,给出了两个数组的使用实例,附带了完整的实现代码,并配有详细注释。

PLKDTHFS的博客 1257

不用写触发器!帆软填报报表自动记录创建/修改时间的终极方案

本文详细介绍了帆软填报报表中无需编写数据库触发器,即可自动记录数据创建时间和修改时间的终极方案。该方案利用帆软内置函数和单元格条件属性,在应用层实现日期自动生成,有效规避了触发器带来的权限、维护和部署难题,为数据填报提供了更轻量、灵活且易于维护的解决方案。

weixin_28040125的博客 359

别再乱点U盘里的.exe了!手把手教你彻底清除那个伪装成Usb Disk的蠕虫病毒

本文详细介绍了如何识别、清除和预防伪装成Usb Disk的蠕虫病毒。从识别感染迹象到安全备份文件,再到深度清理病毒残留和构建防护策略,提供了一套完整的U盘病毒解决方案。特别提醒用户注意U盘病毒的风险,并养成良好的使用习惯。

weixin_30496999的博客 669

c语言修炼秘籍【第七章】const与c语言中一些错误代码

而数组内部的内存使用分配是从低到高的,arr[0]的地址在最低位,当循环进行到第11次 - - arr[11]设置的其实是i的值,此时将 i 的值设为了0,循环继续。这是因为,程序要进行报错也是需要执行时间的,访问arr[11]时程序仍处于循环中,没有时间报错就又进入了下一次循环。test1()可以正常使用指针对n为进行修改,也可以对p指向的位置进行修改。test2()不能通过指针对n进行修改,可以对p指向的位置进行修改。,arr后分配,地址会比i的地址低,分配到的地址为。,i先分配空间,地址为。

PLKDTHFS的博客 674

【NLP】第十章:位置编码Positional Encoding

前面讲RNN时一般都会有一个ht的输出,这个输出就是样本与样本之间的信息,而且RNN是时序循环的,所以RNN本身的结构,在物理上,就自带词的前后顺序信息的。比如词never,不管never本身的词向量是什么,只要你在序列中排第一个位置,你的位置向量就是[0,1,01],你排第三个位置,你的位置向量就是[0.9,-0,4,0.2,1.0]。也所以,你可以理解为:embedding后的词嵌入,PE按照每个样本在sequence中的位置,把embedding后的词嵌入给扭转后,才送入attention的。

因为热爱所以坚持 1917

c语言修炼秘籍【第六章】结构体

将结构体与数组进行对比:数组是一组相同类型的元素集合;结构体是一些值的集合,它们类型可以不同,这些值被称为成员变量。使用结构体类型定义变量int x;int y;} p1;// 声明类型的同时定义变量p1// 定义结构体变量 p2// 初始化:定义变量的同时赋初值struct Stu// 名字int age;// 年龄int data;// 结构体嵌套的初始化// 结构体嵌套的初始化本文对c语言中使用到的结构体进行了简单介绍,更详细的会在后续攻略中详解。

PLKDTHFS的博客 761

Autosar CAN 网络管理标准文档

Autosar CAN 网络管理标准文档

蚂蚁小兵 925

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

c语言修炼秘籍【第四章】操作符

本文会对c语言中使用到的操作符进行介绍,包括算术操作符移位操作符位操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符逗号表达式下标引用、函数调用和结构成员表达式求值单目操作符的种类!// 逻辑反操作- // 负值+ // 正值& // 取地址sizeof // 操作数的类型长度(以字节为单位)~ // 按二进制位取反++ // 前置、后置++-- // 前置、后置--* // 间接访问操作符(解引用操作符) -- 指针的使用。

PLKDTHFS的博客 1136

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

c语言修炼秘籍【第一章】分支与循环语句

在处理现实中的问题时,我们总会遇到需要作出选择或是需要重复多次的完成一种事件。你去图书馆学习,需要日复一日的坚持,每多学一天,你的代码功力就能+1,当你的代码功力,达到了某一程度,你就能够迎娶白富美,走上人生巅峰。为了实现这些目的,c语言提供了分支语句,用以实现选择;提供循环语句,用以实现重复多次的机械活动;表达式语句函数调用语句控制语句复合语句空语句分支、循环语句属于控制语句。控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由各种特定的语句定义符构成;

PLKDTHFS的博客 1244

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第一式】数据的存储

本章节的重点是数据类型详细介绍整型在内存中的的存储:原码、反码、补码大小端字节序介绍及判断浮点型在内存中的存储解析char // 字符数据类型short // 短整型int // 整型long // 长整型long long // 更长的整型float // 单精度浮点数double // 双精度浮点数// c语言有没有字符串类型?// 没有以及他们所占存储空间的大小。使用这个类型开辟内存空间的大小(大小决定了使用范围)如何看待内存空间的视角什么是大端小端?

PLKDTHFS的博客 1487

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第五式】动态内存管理

大家在使用数组时肯定都会有过这样的疑问,如果一个数组的长度不足了,可以延长这个数组吗?使其能够满足存储的需求。又或者是现在不确定数组应该设为多长,先把它放着,等之后再设置它的长度。上面的这些需求,数组显然是无法实现的,那么c语言中有什么东西能够做到这一点呢?动态内存分配!你现在不知道需要多大的空间,没关系,之后你明确了的时候,使用动态内存分配,将你要的空间分配给即可。为什么存在动态内存分配动态内存函数的介绍mallocfreecallocrealloc常见的动态内存错误。

PLKDTHFS的博客 1293

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第六式】文件操作

为什么使用文件什么是文件文件的打开和关闭文件的顺序读写文件的随机读写文本文件和二进制文件文件读取结束的判定文件缓冲区磁盘上的文件就是文件。但是在程序设计上,我们谈到的文件一般有两种:程序文件、数据文件;本节详细的对c语言中数据文件的使用进行了详细的介绍,包括对文件读写操作使用的函数,以及通过文件位置指针的操作函数来对文件进行随机读写,并指出了feof函数可能出现的使用错误,在最后,介绍了文件缓冲区的概念;

PLKDTHFS的博客 1226

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第三式】字符函数和字符串函数

c语言中对字符和字符串的处理非常频繁,但c语言本身是没有字符串类型的,字符串通常存储在常量字符串或字符数组中。常量字符串适用于不需要对其进行修改的字符串函数。strlen函数的作用是获得一个字符串的长度;接收一个const修饰的字符指针变量,这个指针指向的字符串必须有结束符\0;返回一个无符号(易错点)的int类型的数值,表示这个字符串的长度(不包括结束符\0如果没有返回值,则表示出错;// 使用示例int main()printf("a的长度 = %d\n", strlen(a));

PLKDTHFS的博客 926

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第七式】程序的编译

程序的翻译环境程序的执行环境c语言程序的编译+链接预定义符号介绍预处理指令#define宏和函数的对比预处理操作符#和##的介绍命令定义预处理指令#include预处理指令#undef条件编译__FILE__ // 进行编译的源文件__LINE__ // 文件当前行号__DATE__ // 文件被编译的日期__TIME__ // 文件被编译的时间__STDC__ // 如果编译器遵循ANSI C,其值为1,否则未定义。

PLKDTHFS的博客 1195

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第四式】自定义类型详解(结构体、枚举、联合)

c语言中虽然定义得有许多的类型,如char、int、double等等,但是现实生活中需要描述的问题,仅仅使用这些已有类型是不够的,所以在c语言中,程序员可以根据自己的需要,定义出自己的类型结构,以满足需求。结构体:结构体类型的声明结构的自引用结构体变量的定义和初始化结构体内存对齐结构体传参结构体实现位段(位段的填充&可移植性)枚举枚举类型的定义枚举的优点枚举的使用联合联合类型的定义联合的特点联合的使用有了结构体类型,之后应该如何定义变量呢?

PLKDTHFS的博客 989

static 的三种用法:C 语言里一个关键字的三张面孔

本文系统讲解 C 语言中 static 关键字的三种用法:修饰局部变量延长生命周期、修饰全局变量与函数限制作用域到本文件。通过一个包含三个文件的完整工程示例对照演示,并从存储期、作用域与链接性三个属性解释其统一原理,最后补充单元测试框架偏爱 static 函数的工程实践。

大模型全栈工程师 · Thanks_ks 312

【FDE知识库】(1):AI 编程时代开发语言选型分析,云使用go,企业用java,算法python,底层c

AI 编程时代,开发语言选型需综合考量AI适配度、编译速度、跨平台与学习成本。Python以海量语料和即时执行成首选,适用于AI/ML与原型开发;TypeScript凭借类型系统与秒级构建,成为前端及应用层主流;Go以极速编译与统一风格,契合AI代理高效迭代需求。Rust/C++虽性能强,但编译慢、学习成本高,不适于快速试错。综合推荐:优先选Python、TypeScript、Go,兼顾效率与生态,实现最优AI协作体验。

freewebsys的专栏 517
上一篇: c语言修炼秘籍【第四章】操作符
下一篇: c语言修炼秘籍【第六章】结构体
YKPG
博客等级 码龄6年 344粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值