C语言---函数指针基础总结万字(4)

news2024/11/25 10:43:42

一、 函数

1.函数是一段可以重复执行的代码。

它可以接受不同的参数,
完成对应的操作。

下面的例子就是一个函数

int plus(int n) {
  return n;
}

上面的代码声明了一个函数plus()

2.函数声明的语法有以下几点,需要注意。
  • 返回值类型。
    函数声明时,
    首先需要给出返回值的类型,
    上例是int
    表示函数plus()返回一个整数。

  • 参数。
    函数名后面的圆括号里面,
    需要声明参数的类型和参数名,
    plus(int n)表示这个函数有一个整数参数n

  • 函数体。
    函数体要写在大括号里面,
    后面(即大括号外面)不需要加分号。
    大括号的起始位置,
    可以跟函数名在同一行,
    也可以另起一行。

  • return语句。
    return语句给出函数的返回值,
    程序运行到这一行,
    就会跳出函数体,
    结束函数的调用。
    如果函数没有返回值,
    可以省略return语句,
    或者写成return;

3.调用函数时,

只要在函数名后面加上圆括号就可以了,
实际的参数放在圆括号里面,
就像下面这样。

int a = plus(13);
// a 等于 14
4.函数调用时,

参数个数必须与定义里面的参数个数一致(一一对应),
参数过多或过少都会报错。

int plus(int n) {
  return n + 1;
}

plus(2, 2); // 报错
plus();  // 报错

上面示例中,函数plus()只能接受一个参数,传入两个参数或不传参数,都会报错。

5.函数必须声明后使用,

否则会报错。
也就是说,
一定要在使用plus()之前,声明这个函数。
如果像下面这样写,编译时会报错。

int a = plus(13);

int plus(int n) {
  return n + 1;
}

上面示例中,在调用plus_one()之后,才声明这个函数,编译就会报错。

6.C 语言标准规定,

函数只能声明在源码文件的顶层,
不能声明在其他函数内部。

7.没有返回值的函数,

使用void关键字表示返回值的类型。
没有参数的函数,
声明时要用void关键字表示参数类型。

void myFunc(void) {
  // ...
}

上面的myFunc()函数,
既没有返回值,
调用时也不需要参数。

8.函数可以调用自身,

这就叫做递归(recursion)
下面是斐波那契数列的例子。

unsigned long Fibonacci(unsigned n) {
  if (n > 2)
    return Fibonacci(n - 1) + Fibonacci(n - 2);
  else
    return 1;
}

上面示例中,
函数Fibonacci()调用了自身,
这样做可以简化算法。

9.main()

C 语言规定,
main()是程序的入口函数,
即所有的程序一定要包含一个main()函数。
程序总是从这个函数开始执行,
如果没有该函数,
程序就无法启动。
其他函数都是通过它引入程序的。

main()的写法与其他函数一样,
要给出返回值的类型和参数的类型,
就像下面这样。

int main(void) {
  printf("Hello World\n");
  return 0;
}

上面示例中,
最后的return 0;表示函数结束运行,返回0

11.C 语言约定,

返回值0表示函数运行成功,
如果返回其他非零整数,
就表示运行失败,
代码出了问题。
系统根据main()的返回值,
作为整个程序的返回值,
确定程序是否运行成功。

正常情况下,
如果main()里面省略return 0这一行,
编译器会自动加上,
main()的默认返回值为0。
所以,写成下面这样,
效果完全一样。

int main(void) {
  printf("Hello World\n");
}

由于 C 语言只会对main()函数默认添加返回值,
对其他函数不会这样做,
建议总是保留return语句

12.参数的传值引用

如果函数的参数是一个变量,
那么调用时,
传入的是这个变量的值的拷贝,
而不是变量本身。

void increment(int a) {
  a++;
}

int i = 10;
increment(i);

printf("%d\n", i); // 10

上面示例中,
调用increment(i)以后,
变量i本身不会发生变化,
还是等于10
因为传入函数的是i的拷贝,
而不是i本身,
拷贝的变化,
影响不到原始变量。
这就叫做“传值引用(单向值传递)”。
还有一种方法是是双向传递(也叫地址传递)下面会讲解

所以,
如果参数变量发生变化,
最好把它作为返回值传出来。

int increment(int a) {
  a++;
  return a;
}

int i = 10;
i = increment(i);

printf("%d\n", i); // 11

再看下面的例子,Swap()函数用来交换两个变量的值,由于传值引用,下面的写法不会生效。

void Swap(int x, int y) {
  int temp;
  temp = x;
  x = y;
  y = temp;
}

int a = 1;
int b = 2;
Swap(a, b); // 无效

上面的写法不会产生交换变量值的效果,
因为传入的变量是原始变量ab的拷贝,
不管函数内部怎么操作,
都影响不了原始变量。

13…如果想要传入变量本身,

有一个办法,
就是传入变量的地址(地址传递是双向的)。

void Swap(int* x, int* y) {
  int temp;
  temp = *x;
  *x = *y;
  *y = temp;
}

int a = 1;
int b = 2;
Swap(&a, &b);

上面示例中,
通过传入变量xy的地址,
函数内部就可以直接操作该地址,
从而实现交换两个变量的值。

虽然跟传参无关,
这里特别注意下,
函数不要返回内部变量的指针。

int* f(void) {
  int i;
  // ...
  return &i;
}

上面示例中,
函数返回内部变量i的指针,
这种写法是错的。
因为当函数结束运行时,
内部变量就消失了,
这时指向内部变量i的内存地址就是无效的,
再去使用这个地址是非常危险的。

14.函数指针

函数本身就是一段内存里面的代码,
C 语言允许通过指针获取函数。

void print(int a) {
  printf("%d\n", a);
}

void (*print_ptr)(int) = &print;

上面示例中,
变量print_ptr是一个函数指针,
它指向函数print()的地址。
函数print()的地址可以用&print获得。
注意,
(*print_ptr)一定要写在圆括号里面,
否则函数参数(int)的优先级高于*
整个式子就会变成void* print_ptr(int)

有了函数指针,
通过它也可以调用函数。

(*print_ptr)(10);
// 等同于
print(10);

比较特殊的是,
C 语言还规定,
函数名本身就是指向函数代码的指针,
通过函数名就能获取函数地址。
也就是说,
print&print是一回事。

if (print == &print) // true

因此,上面代码的print_ptr等同于print

void (*print_ptr)(int) = &print;
// 或
void (*print_ptr)(int) = print;

if (print_ptr == print) // true

所以,对于任意函数,
都有五种调用函数的写法。

// 写法一
print(10)

// 写法二
(*print)(10)

// 写法三
(&print)(10)

// 写法四
(*print_ptr)(10)

// 写法五
print_ptr(10)

为了简洁易读,
一般情况下,
函数名前面都不加*&

15.这种特性的一个应用是,

如果一个函数的参数或返回值,
也是一个函数,
那么函数原型可以写成下面这样。

int compute(int (*myfunc)(int), int, int);

上面示例可以清晰地表明,
函数compute()的第一个参数也是一个函数。

16.函数原型

前面说过,
函数必须先声明,后使用。
由于程序总是先运行main()函数,
导致所有其他函数都必须在main()函数之前声明。

void func1(void) {
}

void func2(void) {
}

int main(void) {
  func1();
  func2();
  return 0;
}

上面代码中,
main()函数必须在最后声明,
否则编译时会产生警告,
找不到func1()func2()的声明。

但是,
main()是整个程序的入口,
也是主要逻辑,
放在最前面比较好。
另一方面,
对于函数较多的程序,
保证每个函数的顺序正确,
会变得很麻烦。

C 语言提供的解决方法是,
只要在程序开头处给出函数原型,
函数就可以先使用、后声明。
所谓函数原型,
就是提前告诉编译器,
每个函数的返回类型和参数类型。
其他信息都不需要,
也不用包括函数体,
具体的函数实现可以后面再补上。

int twice(int);

int main(int num) {
  return twice(num);
}

int twice(int num) {
  return 2 * num;
}

上面示例中,
函数twice()的实现是放在main()后面,
但是代码头部先给出了函数原型,
所以可以正确编译。
只要提前给出函数原型,
函数具体的实现放在哪里,
就不重要了。

17.函数原型包括参数名也可以,

虽然这样对于编译器是多余的,
但是阅读代码的时候,
可能有助于理解函数的意图。

int twice(int);

// 等同于
int twice(int num);

上面示例中,
twice函数的参数名num
无论是否出现在原型里面,
都是可以的。

注意,
函数原型必须以分号结尾。

一般来说,
每个源码文件的头部,
都会给出当前脚本使用的所有函数的原型。

18.函数说明符

C 语言提供了一些函数说明符,
让函数用法更加明确。

(1)extern 说明符

对于多文件的项目,
源码文件会用到其他文件声明的函数。
这时,当前文件里面,
需要给出外部函数的原型,
并用extern说明该函数的定义来自其他文件。

extern int foo(int arg1, char arg2);

int main(void) {
  int a = foo(2, 3);
  // ...
  return 0;
}

上面示例中,
函数foo()定义在其他文件,
extern告诉编译器当前文件不包含该函数的定义。

不过,
由于函数原型默认就是extern
所以这里不加extern
效果是一样的。

(2)static 说明符

默认情况下,
每次调用函数时,
函数的内部变量都会重新初始化,
不会保留上一次运行的值。
static说明符可以改变这种行为。

static用于函数内部声明变量时,
表示该变量只需要初始化一次,
不需要在每次调用时都进行初始化。
也就是说,
它的值在两次调用之间保持不变。

#include <stdio.h>

void counter(void) {
  static int count = 1;  // 只初始化一次
  printf("%d\n", count);
  count++;
}

int main(void) {
  counter();  // 1
  counter();  // 2
  counter();  // 3
  counter();  // 4
}

上面示例中,
函数counter()的内部变量count
使用static说明符修饰,
表明这个变量只初始化一次,
以后每次调用时都会使用上一次的值,
造成递增的效果。

注意,
static修饰的变量初始化时,
只能赋值为常量,
不能赋值为变量。

int i = 3;
static int j = i; // 错误

上面示例中,
j属于静态变量,
初始化时不能赋值为另一个变量i

另外,
在块作用域中,
static声明的变量有默认值0

static int foo;
// 等同于
static int foo = 0;

static可以用来修饰函数本身。

static int Twice(int num) {
  int result = num * 2;
  return(result);
}

上面示例中,
static关键字表示该函数只能在当前文件里使用,
如果没有这个关键字,
其他文件也可以使用这个函数(通过声明函数原型)。

static也可以用在参数里面,
修饰参数数组。

int sum_array(int a[static 3], int n) {
  // ...
}

上面示例中,static对程序行为不会有任何影响,
只是用来告诉编译器
该数组长度至少为3,
某些情况下可以加快程序运行速度。
另外,
需要注意的是,
对于多维数组的参数,
static仅可用于第一维的说明。

(3)const 说明符

函数参数里面的const说明符,
表示函数内部不得修改该参数变量。

void f(int* p) {
  // ...
}

上面示例中,
函数f()的参数是一个指针p
函数内部可能会改掉它所指向的值*p
从而影响到函数外部。

为了避免这种情况,
可以在声明函数时,
在指针参数前面加上const说明符,
告诉编译器,
函数内部不能修改该参数所指向的值。

void f(const int* p) {
  *p = 0; // 该行报错
}

上面示例中,声明函数时,
const指定不能修改指针p指向的值,
所以*p = 0就会报错。

但是上面这种写法,
只限制修改p所指向的值,
p本身的地址是可以修改的。

void f(const int* p) {
  int x = 13;
  p = &x; // 允许修改
}

上面示例中,
p本身是可以修改,
const只限定*p不能修改。

如果想限制修改p
可以把const放在p前面。

void f(int* const p) {
  int x = 13;
  p = &x; // 该行报错
}

如果想同时限制修改p*p
需要使用两个const

void f(const int* const p) {
  // ...
}

二、指针

几乎任何C语言资料都会提到一句话:

指针是C语言的精华。
出去说会C语言,
但不会指针,
还不如直接说不会C语言。

指针的重要性不言而喻。
然而,
指针重要,
但是又很难,
不容易学好,
那么本章,
我将以更易懂的方式,
让大家认识并理解C语言指针。

关于指针,
我一直认为:
其实每一门语言都有指针,
在学其他语言的时候没听说过,
不过是因为其他语言弱化了这个概念而已,
但实际上指针是存在的。

那么
什么是指针?
为什么要用指针?
怎么用指针?
图解
学习每一个知识点,
都躲不过这三个问题,

1.什么是指针?

首先,需要明确两个概念:

  • 指针是地址,是一个常量。
  • 平时所提到的“指针”,
    其实指的是存储地址的变量,
    准确的来说,
    应该叫做指针变量。

指针变量在定义方面,
和普通变量没什么区别,
但是它存的是变量的地址。

2.为什么要用指针?

在计算机当中,
任何一步操作都是在对内存进行访问。
为了能正确的访问这些存储单元,
就需要给它们编号,
这个编号,
就是地址。

  • 使用指针进行访问,
    即直接访问地址,
    这样效率更高。
  • C语言当中,只有传值,没有引用。
    想要对值进行传递,就必须要通过指针。(在函数部分体会最深)
  • C语言的函数,其实是一个指针。
    没有指针,就没有C语言函数。

3.怎么用指针?

说道怎么用,
那这肯定是这一章都说不完的话题了。
从这四个方面建立对指针的认识

  • (1)指针的定义、初始化和引用方式
  • (2)指针与函数
  • (3)指针与数组
(1)指针的定义、初始化和引用方式

在C语言中,指针是一种特殊的变量,它存储的是另一个变量的内存地址。以下是指针的定义、初始化和引用方式的详细说明:

1)指针的定义
int *p;

其中 int 是指针指向的变量的类型,
*p 是指针的名称。

2)初始化的方式

指针的初始化是指在定义指针的同时给它赋一个初始值。
初始化指针的方式有以下几种:

  1. 初始化为NULL

    int *ptr = NULL;
    

    指针被初始化为NULL,
    表示它不指向任何有效的内存地址。

  2. 初始化为一个变量的地址

    int var = 10;
    int *ptr = &var;
    

    指针 ptr 被初始化为变量 var 的地址。

  3. 初始化为一个常量的地址

    const int const_var = 20;
    int *ptr = &const_var;
    

    指针 ptr 被初始化为常量 const_var 的地址。

  4. 初始化为另一个指针的值

    int *ptr1 = &var;
    int *ptr2 = ptr1;
    

    ptr2 被初始化为 ptr1 的值,即 var 的地址。

  5. 动态内存分配

    int *ptr = (int *)malloc(sizeof(int));
    

    使用 malloc 函数动态分配了一个整型大小的内存,并让指针 ptr 指向这块内存。

3)引用方式
引用指针指向的值,可以使用解引用操作符 `*`。以下是几种引用指针的方式:
  1. 直接解引用

    int value = *ptr;
    

    value 被赋值为指针 ptr 指向的值。

  2. 在表达式中解引用

    *ptr = 30;
    

    将指针 ptr 指向的值设置为30。

  3. 作为函数参数

    void update(int *ptr) {
        *ptr = 40;
    }
    

    函数 update 接受一个整型指针作为参数,并修改它指向的值。

  4. 数组和指针

    int arr[5] = {1, 2, 3, 4, 5};
    int *ptr = arr;
    int value = *(ptr + 2); // 引用数组第三个元素
    

    value 被赋值为数组 arr 的第三个元素。

  5. 字符串和指针

    char str[] = "Hello";
    char *ptr = str;
    char ch = *ptr; // 'H'
    

    ch 被赋值为字符串 str 的第一个字符。

通过这些方式
可以有效地使用指针来访问和操作内存中的数据。

(2)指针与函数

之前在介绍指针时,
提到过一句话:

C语言当中,
只有传值,
没有引用。
想要对值进行传递,
就必须要通过指针。

这句话什么意思?

1.传值

之前学习函数的时候遇到一个问题,
实参与形参都有自己独立的内存空间,
所以不通过指针,
进行交换两个数的操作,
达不到想到的结果。
下面是以前的例子:

void swap(int a, int b) {

    int temp = a;
    a = b;
    b = temp;
}

因为在这个步骤中,只有传值,
并没有真正修改到实参的内容。
对于这个问题,
现在我们用指针来解决:

void swap(int *a, int *b) {

    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {

    int a = 4, b = 6;
    swap(&a, &b);
}

思考:如果将上面的swap函数修改为一下形式,
能达到交换效果吗?

void swap(int *a, int *b) {

    int *temp = a;
    a = b;
    b = temp;
}
(3)指针与数组

数组是由若干个元素组成的,
每一个元素都有独立的存储空间,
并且地址连续。
而数组名,
就是这一块连续内存的首地址。
既然如此,
我们也可以使用指针来指向这一块地址。

int a[10] = {1, 2, 3, 4, 5, 6};
int *p = a;  // a不用写成&a,因为a作为数组名,本身就是地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2118121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mac电脑IDEA2024安装后打不开问题解决

Mac电脑IDEA2024安装后打不开问题解决 由于电脑系统升级&#xff0c;导致我用的2019版本的IDEA一打开就卡&#xff0c;机缘巧合拥有了一个正版的IDEA账号&#xff0c;下载2024版本的IDEA&#xff0c;打开报错。 由于电脑系统升级&#xff0c;导致我用的2019版本的IDEA一打开就卡…

Day20_0.1基础学习MATLAB学习小技巧总结(20)——MATLAB绘图篇(3)

利用空闲时间把碎片化的MATLAB知识重新系统的学习一遍&#xff0c;为了在这个过程中加深印象&#xff0c;也为了能够有所足迹&#xff0c;我会把自己的学习总结发在专栏中&#xff0c;以便学习交流。 参考书目&#xff1a;《MATLAB基础教程 (第三版) (薛山)》 之前的章节都是…

项目实战系列三: 家居购项目 第五部分

&#x1f333;显示订单[订单管理] &#x1f333;暂时缺货 需求分析 1.如果某家居库存为0, 首页的"Add to Cart" 按钮显示为"暂时缺货" 2.后台也加上校验. 只有在 库存>0 时, 才能添加到购物车 代码实现 1.修改web/views/customer/index.jsp <c:if…

网络层 VIII(网络层设备——路由器)【★★★★★★】

一、冲突域与广播域 这里的“域”表示冲突或广播在其中发生并传播的区域。 1. 冲突域 冲突域是指连接到同一物理介质上的所有结点的集合&#xff0c;这些结点之间存在介质争用的现象&#xff08;能产生冲突的所有设备的集合&#xff09;。也就是说&#xff0c;若这些设备同时发…

ABeam德硕 | 海立集团BI项目正式启动,ABeam中国助力实现以数据之力驱动经营管理

9月2日&#xff0c;由德硕管理咨询&#xff08;上海&#xff09;有限公司作为实施合作伙伴的海立集团BI项目正式启动&#xff0c;海立集团党委书记、总经理缪骏、ABeam大中华区董事长兼总经理中野洋辅出席项目启动仪式。 ABeam大中华区董事长兼总经理中野洋辅 在致辞中表示&am…

【vue+el-table】表格操作列宽度跟随按钮个数自适应, 方法封装全局使用

效果图 以上图片分别代表不同用户权限下所能看到的按钮个数, 操作列宽度也会自适应宽度, 就不会一直处于最大宽度, 导致其他权限用户看到的页面出现大量留白问题. 目录 解决方法解决过程中可能出现的问题width赋值时为什么不放update()中btnDom为什么不能直接调用forEach为…

【网络原理】❤️Tcp 连接管理机制❤️ “三次握手” “四次挥手”的深度理解, 面试最热门的话题,没有之一, 保姆式教学 !!!

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

杰发科技Bootloader(3)—— 基于7801的APP切到Boot

为了方便在APP中跳转到Boot重新进行升级&#xff0c;有两种办法&#xff0c;7840同样可以使用。 1. 调用reset接口进行复位&#xff0c;复位后会先进Boot&#xff0c;再自动跳转到App。 NVIC_SystemReset(); 2. 直接使用跳转指令&#xff0c;参考Boot跳转到App代码&#xff0…

有哪些常用的企业统一门户?为何选择移动应用管理平台WorkPlus

企业统一门户是为了解决企业内部应用分散、管理繁琐的问题&#xff0c;提供集成化的应用平台&#xff0c;旨在提高员工的工作效率和便利性。而在众多的企业统一门户中&#xff0c;作为一款领先的移动应用管理平台&#xff0c;WorkPlus备受青睐。本文将介绍一些常用的企业统一门…

Sentinel 控制界面

一、下载 可视化jar 二、cmd 启动 jar java -Dserver.port8718 -Dcsp.sentinel.dashboard.server127.0.0.1:8718 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.2.jar 页面访问&#xff1a; http://localhost:8718/#/dashboard/

Elasticsearch Suggesters 自动补全长度设置

问题&#xff1a;在用户输入之后联想词返回长度默认为50&#xff0c;导致返回结果不完全 原因&#xff1a;completion 字段索引时允许存储的文本长度受 max_input_length 参数控制&#xff08;默认为 50 字符&#xff09;。可以在 mapping 中调整这个值 解决&#xff1a;“max…

【西电电装实习】焊接台组、焊接技巧

前言 工训中心 - 电装实习&#xff0c;进行实操的笔记 --- 一、焊台 二、焊枪大功率的握法&#xff08;反握法&#xff09; 三、余锡擦拭 四、pcb板与焊盘 五、焊接技巧 先加热焊盘&#xff0c;再上锡&#xff08;不能不加热焊盘&#xff0c;让锡往下漏&#xff09;上锡的时…

首届世界风筝创意大赛专家委员会成立 艺术大咖共话“风筝文化”

9月6日上午&#xff0c;世界风筝公园首届世界风筝创意大赛专家委员会成立暨座谈会在世界风筝公园召开。来自清华大学、中央音乐学院、中国美术学院等院校的专家学者及国际知名艺术家、设计师齐聚一堂&#xff0c;共同成立大赛专家委员会&#xff0c;并探讨以风筝为主题的艺术创…

简单的springboot log4j2日志配置

简单的springboot log4j2日志配置 1.简介 Log4j2 是 Apache Software Foundation 开发的一个日志记录工具&#xff0c;它是 Log4j 的后续版本&#xff0c;并且在多个方面进行了改进。以下是 Log4j2 的一些关键特性&#xff1a; 性能提升&#xff1a;Log4j2 在设计上做了很多优…

内裤洗衣机哪个牌子好又实惠?诚意盘点五款绝佳内衣洗衣机!

在当今繁忙的生活中&#xff0c;内衣洗衣机已成为我们日常生活中不可或缺的家电。但是&#xff0c;面对市场上众多品牌的内衣洗衣机&#xff0c;那么&#xff0c;到底内衣洗衣机哪个牌子好&#xff1f;本次我将在这篇文章中探讨内衣洗衣机的选购策略&#xff0c;以帮助大家找到…

Java并发编程实战 10 | 线程安全问题

什么是线程安全&#xff1f; 《Java并发实践》的作者 Brian Goetz 对线程安全的定义是&#xff1a;当多个线程访问同一个对象时&#xff0c;如果无需考虑这些线程在运行时的调度策略和交替执行顺序&#xff0c;也不需要进行额外的同步处理&#xff0c;仍然能够得到正确的结果&…

C语言--12字符串处理函数

函数strstr 函数strchr与strrchr 注意&#xff1a; 这两个函数的功能&#xff0c;都是在指定的字符串 s 中&#xff0c;试图找到字符 c。strchr() 从左往右找第一个&#xff0c;strrchr() 从左往右找最后一个。字符串结束标记 ‘\0’ 被认为是字符串的一部分。 函数strlen 示例…

一款免费开源功能丰富的看图软件NeeView

NeeView 是一款功能丰富的图像查看软件&#xff0c;它以其独特的浏览体验和广泛的支持格式受到用户的欢迎。NeeView 不仅可以浏览普通的图像文件&#xff0c;还能够查看压缩包内的图片、预览PDF文档甚至播放视频文件。 NeeView 的主要特点&#xff1a; 多格式支持&#xff1a…

《人工智能安全治理框架》1.0版

人工智能是人类发展新领域&#xff0c;给世界带来巨大机遇&#xff0c;也带来各类风险挑战落实《全球人工智能治理倡议》&#xff0c;遵循“以人为本、智能向善”的发展方向&#xff0c;为推动政府、国际组织、企业、科研院所、民间机构和社会公众等各方&#xff0c;就人工智能…

无人机之穿越机的类型

穿越机&#xff0c;即FPV Drone或Racing Drone&#xff0c;是一种主要通过第一人称视角&#xff08;FPV&#xff09;进行操作的无人机。这种无人机通常配备有四个电机和相应的飞控系统&#xff0c;使其具有极高的飞行自由度和速度。穿越机的类型多样&#xff0c;可以从不同角度…