C语言 指针
含义
从根本上看,指针是一个值为内存地址的变量(或数据对象)。指针变量的值是地址。
要创建指针变量,先要声明指针变量的类型
作用
1.实现复杂的数据结构,例如数组、链表、队列和堆栈等;
2.能方便地表示和处理字符串;
char s1[20]={'a','b','\0'},*sp1;
sp1=s1; //s1和sp1都代表字符串"ab"
3.实现动态存储分配;
对于程序中所包含的大存储量的数据对象,一般用预先定义指针变量来表示,当实际使用时才临时申请实际的存储空间,使用完毕立即释放。
指针变量所占的内存空间与所表示的数据对象的存储空间相比实在是微乎其微,因为它只是用来存放对应空间的首地址,而不是存放数据本身,所以可以节省大量的存储空间,提高内存空间的利用率。
4.在函数之间进行数据的双向传递;
将形参定义成指针类型,对应的实参必须是某个数据对象的地址或首地址,也即采用传地址的方式,这样就可以实现数据的双向传递了。
类型
指针类型属于非标准类型,其取值是所表示的数据对象的内存地址,所以其值域是内存地址集。
指针类型用来定义各种类型的指针变量。
<类型标识符>*
类型标识符,是指针类型的基类型,也即指针所指向的数据对象的类型。
*,作用在各个标识符上,表示该标识符所标识的变量是指针变量。
指针类型定义和指针变量声明是同时进行的。
int *a,b; //既定义了整型指针int*,又声明了整型指针变量a和整型变量b。
声明指针
类型 * 名称
指针实际上是一个新类型,不是整数类型。
指针变量的作用域
指针变量也有全局和局部之分:在函数外部声明的指针变量是全局的;在函数内部声明的指针变量是局部于该函数的。
指针变量的初始化
可以在定义指针变量的同时给其赋初值,指针的初值是某个数据对象的内存地址,也使得该指针指向对应的数据对象。
这一过程也称为建立指针。
int i=10;
int *iptr=&i; //在声明指针变量iptr的同时赋予初值,其初值是i的地址。
说明
1.标识符前面的“*”并不是名称的一部分,而表示该数据对象的类型为指针类型,也即声明该数据对象是指针类型数据对象。
2.指针变量可以和其它变量在同一语句中声明。
double d1,*d2;
3.指针变量只能存放相同基类型数据对象的内存地址,话句话说,一个指针变量在任何时候都只能指向同一基类型的数据对象。
char*c;
int i;
......
c=&i; //错误,因为c只能指向字符串
使用指针在函数间通信
一般而言,可以把变量相关的两类信息传递给函数。
1.function1(x)
传递的是x的值
2.function2(&x)
传递的是x的地址
如果要计算和处理值,那么使用第1种形式的函数调用;如果要在被调函数中改变主调函数的变量,则使用第2种形式的函数调用。
变量:名称、地址和值
通过前面的讨论发现,变量的名称、地址和变量的值之间关系密切。
编写程序时,可以认为变量有两个属性:名称和值(还有其他性质,如类型,暂不讨论)。计算机编译和加载程序后,认为变量也有两个属性:地址和值。地址就是变量在计算机内部的名称。
在许多语言中,地址都归计算机管,对程序员隐藏。然而在 C 中,可以通过&运算符访问地址,通过*运算符获得地址上的值。例如,&barn表示变量barn的地址,使用函数名即可获得变量的数值。例如,printf("%d\n",barn)打印barn的值,使用*运算符即可获得储存在地址上的值。如果pbarn=&barn;,那么*pbarn表示的是储存在&barn地址上的值。
简而言之,普通变量把值作为基本量,把地址作为通过&运算符获得的派生量,而指针变量把地址作为基本量,把值作为通过*运算符获得的派生量。
虽然打印地址可以满足读者好奇心,但是这并不是&运算符的主要用途。更重要的是使用&、*和指针可以操纵地址和地址上的内容,如swap3.c630程序(程序清单9.15)所示。
数组和指针
现在可以更清楚地定义指向int的指针、指向float的指针,以及指向其他 数据对象的指针。
指针的值是它所指向对象的地址。地址的表示方式依赖于计算机内部的 669 硬件。许多计算机(包括PC和Macintosh)都是按字节编址,意思是内存中 的每个字节都按顺序编号。这里,一个较大对象的地址(如double类型的变 量)通常是该对象第一个字节的地址。
在指针前面使用*运算符可以得到该指针所指向对象的值。
指针加1,指针的值递增它所指向类型的大小(以字节为单位)。
可以使用指针标识数组的 元素和获得元素的值。从本质上看,同一个对象有两种表示法。实际上,C 语言标准在描述数组表示法时确实借助了指针。
函数 、数组和指针
只有在函数原型或函数定义头中, 才可以用int ar[]
代替int * ar
。
int *ar
形式和int ar[]
形式都表示ar是一个指向int的指针。但是,int ar[]
只 能用于声明形式参数。第2种形式int ar[]
提醒读者指针ar指向的不仅仅 一个int类型值,还是一个int类型数组的元素。
声明数组形参
因为数组名是该数组首元素的地址,作为实际参数的数组名要求形式参 数是一个与之匹配的指针。只有在这种情况下,C才会把int ar[]
和int * ar
解 释成一样。也就是说,ar是指向int的指针。由于函数原型可以省略参数名, 所以下面4种原型都是等价的:
int sum(int *ar, int n);
int sum(int *, int);
int sum(int ar[], int n);
int sum(int [], int);
但是,在函数定义中不能省略参数名。下面两种形式的函数定义等价:
int sum(int *ar, int n)
{
// 其他代码已省略
}
int sum(int ar[], int n);
{
//其 他代码已省略
}
可以使用以上提到的任意一种函数原型和函数定义。
使用指针形参
函数要处理数组必须知道何时开始、何时结束。sum()函数使用一个指 针形参标识数组的开始,用一个整数形参表明待处理数组的元素个数(指针 形参也表明了数组中的数据类型)。但是这并不是给函数传递必备信息的唯 一方法。还有一种方法是传递两个指针,第1个指针指明数组的开始处(与 前面用法相同),第2个指针指明数组的结束处。
指针表示法和数组表示法
使用数组表示法,让函数处理数组的这一意图更加明显。
指针表示法更接近机器语言,因此一些编译器在编译时能生成效率更高的代码。
指针操作
赋值
可以把地址赋给指针。
解引号
* 运算符给出指针指向地址上存储的值
取址
和所有变量一样,指针变量也有自己的地址和值。对指针而言, &运算符给出指针本身的地址。
指针与整数相加
可以使用+运算符把指针与整数相加,或整数与指针 相加。无论哪种情况,整数都会和指针所指向类型的大小(以字节为单位) 相乘,然后把结果与初始地址相加。如果相加 的结果超出了初始指针指向的数组范围,计算结果则是未定义的。除非正好 超过数组末尾第一个位置,C保证该指针有效。
递增指针
递增指向数组元素的指针可以让该指针移动至数组的下一个元素。
指针减去一个整数
可以使用-运算符从一个指针中减去一个整数。指针必须是第1个运算对象,整数是第二个运算对象。该整数将乘以指针指向类型的大小(以字节为单位),然后用初始地址减去乘积。如果相减的结果超出了初始指针所指向数组的范围,计算结果则是未定义的。除非正好超过数组末尾第一个位置,C保证该指针有效。
递减指针
前缀和后缀的递增或递减运算符都可以使用。
指针求差
可以计算两个指针的差值。通常,求差的两个指针分别指向同一个数组的不同元素,通过计算求出两元素之间的距离。差值的单位与数组类型的单位相同。只要两个指针都指向相同的数组(或者其中一个指针指向数组后面的第1个地址),C都能保证相减运算有效。如果指向两个不同数组的指针进行求差运算,可能会得出一个值,或者导致运行时错误。
比较
使用关系运算符可以比较两个指针的值,前提是两个指针都指向相同类型的对象。
PS:这里的减法有两种。可以用一个指针减去另一个指针。
在递增或递减指针时还要注意一些问题。编译器不会检查指针是否仍指向数组元素。C只能保证指向数组任意元素的指针和指向数组后面的第一个位置的指针有效。但是,如果递增或递减一个指针后超出了这个范围,则是未定义的。另外,可以解引用指向数组任意元素的指针。但是,即使指针指向数组后面一个位置是有效的,也不能保证可以解引这样的越界指针。
解引用未初始化的指针
千万不要解引用未初始化的指针。
创建一个指针时,系统只分配了存储指针本身的内存,并未分配存储数据的内存。因此,在使用指针之前,必须先用已分配的地址初始化它。
指针的基本用法
1.在函数间传递信息。
2.用在处理数组的函数中。
传递值还是传递指针?
编写一个处理基本类型(如,int)的函数时,要选择是传递int类型的值还是传递指向int的指针。通常都是直接传递数值,只有程序需要在函数中改变该数值时,才会传递针。对于数组别无选择,必须传递指针,因为这样做效率高。如果一个函数按值传递数组,则必须分配足够的空间来储存原数组的副本,然后把原数组所有的数据拷贝至新的数组中。如果把数组的地址传递给函数,让函数直接处理原数组则效率要高。
传递地址会导致一些问题。C 通常都按值传递数据,因为这样做可以保证数据的完整性。如果函数使用的是原始数据的副本,就不会意外修改原始数据。但是,处理数组的函数通常都需要使用原始数据,因此这样的函数可以修改原数组。
空字符和空指针
从概念上看,两者完全不同。空字符(或'\0')是用于标记C字符串末尾的字符,其对应字符编码是0。由于其他字符的编码不可能是 0,所以不可能是字符串的一部分。
空指针(或NULL)有一个值,该值不会与任何数据的有效地址对应。通常,函数使用它返回一个有效地址表示某些特殊情况发生,例如遇到文件结尾或未能按预期执行。
空字符是整数类型,而空指针是指针类型。两者有时容易混淆的原因是:它们都可以用数值0来表示。但是,从概念上看,两者是不同类型的0。
另外,空字符是一个字符,占1字节;而空指针是一个地址,通常占4字节。
指针运算
指针的赋值
1.赋空值(NULL)
2.赋予某个变量的地址
3.将一个指针变量的值赋予另一指针变量
int grade,*p;
p=&grade;
指针的加减运算
运算符:+、-、++、--
一个指针量加上(或减去)一个整型量n,表示地址偏移了n个单位,具体向上或向下偏移多少字节,取决于其基类型。
例如:一个整型指针变量加上4等于原存放的地址值加上8字节;而一个双精度型指针加上4等于原存放的地址值加上32字节。
PS:参与运算的指针变量必须是已赋值的。
对数组名施加+、-运算:数组名的初值是数组的首地址,也即指向数组的第一个元素,数组名+i,表示指向数组的第i+1个元素。
a[i]与*(a+i)这两种表示法是等价的,都表示a数组的第i+1个元素。
指针变量的++、--运算:
++:原地址加上一个地址单位(基类型的实际字节数)
--:原地址减去一个地址单位(基类型的实际字节数)
int *iptr;
......
iptr++; //iptr=iptr+1向下移动两个字节
iptr--; //iptr=iptr-1向上移动两个字节
取地址运算
运算符:&
作用:获取数据对象的内存地址,如果是结构数据对象,则获取其内存首地址
间接访问
运算符:*
该运算符作用在指针变量上,表示访问指针变量所指向的数据对象。
作用
实现对指针所指向的数据对象的间接访问,包括引用和赋值等基本运算。
int a,b=2,c,*p;
......
p=&b;
scanf("%d",&a);
c=a+*p;
c=a+b
"*"的说明
1.作为运算符,表示乘法
2.作为类型标识符,用来定义指针类型(出现在数据定义部分)
3.作为指针运算符,表示间接访问
指针与数组
数组名用来存放数组的内存首地址,也是第一个数组元素的内存地址,因此数组名是一种特殊的指针变量。
数组名是指向数组元素的指针变量
对于数组a而言,数组名a和a中的各个元素的关系如下:a=&a[0];a+i=&a[i]。数组元素的下标描述可以用数组名指针的偏移来代替,所以可以用指针来间接访问数组元素。
*a=a[0],*(a+i)=a[i]
指针数组
元素的数据类型是指针的数组称为指针数组。
char *name[]={"Lin","Ding","Zhan"};
赋初值后,name数组的每一个元素的值并不是学生的姓名(字符串),而是对应字符串的首地址,每一个元素的值是一个字符指针,该指针指向对应的字符串。
指向指针的指针
对于指针数组而言,其数组名是指针,而且是指向指针的指针,称为二级指针。因此除了描述成指针数组之外,还可以描述成**类型。
char*name[]={"Lin","Ding","Zhan"};
char**pname;
......
pname=name;
执行pname=name后,pname可以表示指针数组name,也即:pname指向name[0],pname指向name[1]......以此类推。
cout<<(int)arr[i]
是输出字符指针(字符串地址);
cout<<arr[i]
是输出字符指针所指向的字符串。
指针与函数
函数与指针的关系:
1.函数的参数是指针类型数据,例如数组参数、指针变量参数......
2.函数返回值类型本身就是指针类型,这种函数称为指针函数
3.函数名本身就是指向函数入口地址的指针,因此可以声明一种指针数据用来存放函数名,这样的指针称为函数指针
函数的指针类型参数
形式
可以定义成指针变量或数组
作用
返回函数对指针的修改,实质上是返回函数对指针所指向的数据对象的修改,这样可以返回不止一个值,同时还可以节省大量的内存空间,因此具有很大的灵活性与实用性。
带有指针参数的函数的实现过程
1.在函数的参数表中定义指针类型参数void swap(int *x,int *y)
2.在函数调用时提供相应的变量或数组地址(传地址)swap(&a,&b);
3.函数的执行部分对指针形参进行间接访问
使用指针类型参数的副作用
指针类型参数的灵活性体现在它使函数可以访问本函数的局部空间(栈空间)以外的内存区域,这显然破坏了函数的黑盒特性,带来以下副作用:
1.可读性问题:对数据的间接访问比直接访问相对难以理解。
2.重用性问题:函数调用依赖于上层函数或整个外部内存空间环境,丧失其封装特性(黑盒特性),所以无法作为公共模块来使用。
3.调试的复杂性问题:跟踪错误的区域从函数的局部数据区扩大到整个内存空间,不但要跟踪变量
函数指针
程序运行时,每个函数都存放在代码区中,有一个入口地址,称为函数地址,函数名就表示该地址。
指向函数地址的指针称为函数指针,通过该指针可以调用相应的函数。、
作用:调用函数和做函数的参数
声明
类型标识符名(*指针变量名)(参数列表)
用函数指针调用函数
函数指针变量(参数列表)
(*函数指针变量名)(参数列表)
函数指针用作函数参数
当函数形参是函数指针时,对应的实参必须是函数名
char f2(int(*fp1(int)))
......
f2(f1)
实参是函数名,在函数调用时实现函数地址的传递,这样可以在被调函数体内,通过对函数指针形参的引用来调用另一函数,而且对应不同的实参值可以调用不同的函数。
函数指针和指针函数的区别
函数指针是指向函数的指针变量,即本质是一个指针变量;指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针,格式为类型标识符*函数名(参数列表)
指针函数
该函数的返回值是一个地址值,函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有“函数返回值”,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。
定义类型名*函数名(参数列表)
( )的优先级高于*,所以参数名先和参数列表结合,再和*结合。
相关文章:

C语言 指针
含义 从根本上看,指针是一个值为内存地址的变量(或数据对象)。指针变量的值是地址。 要创建指针变量,先要声明指针变量的类型 作用 1.实现复杂的数据结构,例如数组、链表、队列和堆栈等; 2.能方便地表…...

YOLOv8血细胞检测(7):小目标大目标一网打尽,轻骨干重Neck的轻量级GFPN | 阿里ICLR2022 GiraffeDet
💡💡💡本文改进:小目标大目标一网打尽GFPN,提升大小目标检测性能 GFPN | 亲测在血细胞检测项目中涨点,map@0.5 从原始0.895提升至0.904 收录专栏: 💡💡💡YOLO医学影像检测:http://t.csdnimg.cn/N4zBP ✨✨✨实战医学影像检测项目,通过创新点验证涨点可…...

广度优先(BFS)(例子:迷宫)
广度优先搜索算法(BFS)是一种用于图形和树数据结构的搜索算法。该算法从根节点开始搜索,然后依次访问每个相邻节点。在搜索过程中,每个节点都标记为已访问,以避免重复访问。BFS算法适用于寻找最短路径的问题࿰…...

【安卓源码】安卓Watchdog 机制
在Android系统中,也设计了一个软件层面Watchdog,用于保护一些重要的系统服务,比如:AMS、WMS、PMS等,由于以上核心服务运行在system_server进程里面,所以当以上服务出现异常时,通常会将system_se…...

inscode连接不上gpu,持续8小时,为了数据不丢失续费了6小时,我只想知道什么时候可以连接
并且给我相应的补偿...

QT位置相关函数
Qt(Qt Framework)是一个流行的C应用程序开发框架,提供了丰富的位置相关函数和类,用于处理窗口、窗口小部件和图形的位置和几何操作。以下是一些常用的Qt位置相关函数和类: QPoint:QPoint类表示一个二维点的…...

vulnhub靶场 Kioptrix-level-1
简介: vulnhub是一个提供靶场环境的平台。而Kioptrix-level-1就是一个对新手比较友好的靶场。初学渗透的同学可以做做试试看,项目地址如下。 项目地址:Kioptrix: Level 1 (#1) ~ VulnHub 信息收集 查看本机IP,靶机跟kali都是使用…...

全网最细,真实企业性能测试落地实施,一文带你快速打通...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、什么是性能测试…...

三十一、【进阶】B+树的演变过程
1、B树简单介绍 (1)介绍:B树也属于B树,是B树的变种 (2)特点:所有的数据都位于叶子节点上,叶子节点上的所有元素形成了一个单项链表 (3)图示: 2…...

算法通过村第十三关-术数|白银笔记|术数高频问题
文章目录 前言数组实现加法专题数组实现整数加法字符串加法二进制加法 幂运算专题求2的次幂求3的次幂求4的次幂 总结 前言 提示:人心本易趋死寂,苦难之后,焕然重建,激荡一阵,又趋麻木。 --苏枕书《有鹿来》 我们继续看…...

Java 线程的生命周期
🙈作者简介:练习时长两年半的Java up主 🙉个人主页:程序员老茶 🙊 ps:点赞👍是免费的,却可以让写博客的作者开兴好久好久😎 📚系列专栏:Java全栈,…...

Vue页面监听键盘按键的多种方法
在Vue页面中,可以使用多种方法来监听键盘按键。以下是至少五种常用的方法: 使用keydown或keyup指令来绑定键盘按键事件。 <template><div><input type"text" keydown.enter"handleEnterKey" /></div> <…...

解析硬件连通性测试的重要性及测试方法
在现代科技世界中,硬件设备的复杂性和多样性已经达到了前所未有的水平。无论是计算机、智能手机、物联网设备还是嵌入式系统,各种硬件组件的协同工作对于设备的正常运行至关重要。硬件连通性测试是确保这些组件相互配合无误的重要步骤。 一、硬件连通性测…...

Hive窗口函数回顾
1.语法 1.1 基于行的窗口函数 Hive的窗口函数分为两种类型,一种是基于行的窗口函数,即将某个字段的多行限定为一个范围,对范围内的字段值进行计算,最后将形成的字段拼接在该表上。 注意:在进行窗口函数计算之前&#…...

flink自定义窗口分配器
背景 我们知道处理常用的滑动窗口分配器,滚动窗口分配器,全局窗口分配器,会话窗口分配器外,我们可以实现自己的自定义窗口分配器,以实现我们的自己的窗口逻辑 自定义窗口分配器的实现 package wikiedits.assigner;i…...

iOS CGRect CGPoint NSRange等结构体的NSLog打印输出
iOS的UIKit里提供了UIGeometry.h内有各结构体转换成NSString的方法,可用于打印输出; UIKIT_EXTERN NSString *NSStringFromCGPoint(CGPoint point); UIKIT_EXTERN NSString *NSStringFromCGVector(CGVector vector); UIKIT_EXTERN NSString *NSStringFr…...

Viper FTP Mac/ftp管理工具
Viper FTP 是一个用于文件传输和管理的 Mac 应用程序。它允许用户上传、下载和管理远程服务器上的文件,以及在不同本地文件夹之间传输文件。 Viper FTP 支持广泛的文件传输协议,包括 FTP、SFTP、WebDav、Amazon S3、Google Drive 等。它还包括文件同步、…...

web漏洞-xml外部实体注入(XXE)
web漏洞-xml外部实体注入(XXE) 目录 web漏洞-xml外部实体注入(XXE)概念危害检测方法利用方法漏洞利用xxe-lab有回显情况无回显情况 pikachu靶场有回显内容无回显 修复方案 概念 xml可拓展标记语言: xml是一种可拓展的标…...

Impeller-Flutter的新渲染引擎
Impeller是什么?它本质上是怎样运行的? Impeller是Flutter的新的渲染引擎,直到现在Flutter正在用一个叫做Skia的渲染引擎。 问题是Skia不是为了Flutter量身定做的。它有为范围广阔的设备构建的一大堆的渲染特性,这意味着它并不总…...

python 面试算法题
1.第一题 题目描述:给定两个字符串, s 和 goal。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true 。 s 的 旋转操作 就是将 s 最左边的字符移动到最右边。 例如, 若 s abcde,在旋转一次之后结果就是bcdea 。 示例一: 输入: s &quo…...

Python中的yield关键字
基本概念 yield 是 Python 中的一个关键字,主要在定义生成器函数时使用。使用 yield 的函数在调用时返回一个特殊的迭代器,称为生成器。不同于常规的函数返回一个单一的值(如数字、字符串或其他对象),带有 yield 的函…...

怎么压缩pdf文件?分享缩小pdf文件的简单方法
在我们的日常生活和工作中,往往需要处理大量的PDF文件,而很多时候这些文件的大小会成为传输和存储的难题。为了解决这个问题,下面我们将介绍三种方法来压缩PDF文件,一起来看看吧~ 一、嗨格式压缩大师 首先,最简单也是…...

51单片机可调幅度频率波形信号发生器( proteus仿真+程序+原理图+报告+讲解视频)
51单片机可调幅度频率信号发生器( proteus仿真程序原理图报告讲解视频) 讲解视频1.主要功能:2.仿真3. 程序代码4. 原理图4. 设计报告5. 设计资料内容清单&&下载链接***[资料下载链接](https://docs.qq.com/doc/DS1daV1BKRXZMeE9u)*** 51单片机可…...

Vuex的介绍
介绍 :::warning 注意 在阅读此文章之前请确保你已经掌握了组件中的选项 data、计算属性 computed、methods 方法等相关知识。 ::: 什么是 Vuex? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以…...

mysql基础语法速成版
mysql基础语法速成版 一、前言二、基础语法2.1 数据库操作2.2 MySQL数据类型2.3 表操作2.3.1 表的创建、删除,及表结构的改变2.3.2表数据的增删改查2.3.4 like模糊查询2.3.5 UNION 操作符2.3.6 order by排序2.3.7 group by分组2.3.8 join连接2.3.9 null处理2.3.10 m…...

Docker镜像 配置ssh
安装 1.安装ssh 2.设置root密码 RUN echo root:123456 | chpasswd 3.设置sshd config RUN echo Port 22 >> /etc/ssh/sshd_config RUN echo PermitRootLogin yes >> /etc/ssh/sshd_config4.设置开机启动 RUN mkdir /var/run/sshd #没有这个目录,s…...

12.2 实现键盘模拟按键
本节将向读者介绍如何使用键盘鼠标操控模拟技术,键盘鼠标操控模拟技术是一种非常实用的技术,可以自动化执行一些重复性的任务,提高工作效率,在Windows系统下,通过使用各种键盘鼠标控制函数实现动态捕捉和模拟特定功能的…...

《DevOps 精要:业务视角》- 读书笔记(七)
DevOps 精要:业务视角(七) DevOps历程什么是企业体系的DevOps?DevOps的目标是什么? DevOps的知识体系规范敏捷持续交付IT服务管理以TPS理念为基础 DevOps团队角色流程主管(Process Master)服务主管…...

【随想】每日两题Day.12(实则一题)
题目:15. 三数之和 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意:答案中不…...

基于复旦微JFM7K325T FPGA的高性能PCIe总线数据预处理载板(100%国产化)
PCIE711是一款基于PCIE总线架构的高性能数据预处理FMC载板,板卡采用复旦微的JFM7K325T FPGA作为实时处理器,实现各个接口之间的互联。该板卡可以实现100%国产化。 板卡具有1个FMC(HPC)接口,1路PCIe x8主机接口&#x…...