<C语言>指针的深度学习

目录

一、字符指针

二、指针数组

三、数组指针 

1.数组指针的定义

2.&数组名与数组名

3.数组指针的使用

四、数组参数、指针参数

1.一维数组传参

2.二维数组传参 

3.一级指针传参

4.二级指针传参

五、函数指针

 六、函数指针数组

七、指向函数指针数组的指针

八、回调函数

1. 回调函数概念

 九、指针笔试题


一、字符指针

指针类型中 char * 为字符指针

一般使用:

int main()
{char ch = 'w';char *pc = &ch;*pc = 'w';return 0;
}

 另一种使用方式:

int main()
{const char* ptr = "hello world";//常量字符串不能被修改,所以用const修饰printf("%s", ptr);return 0;
}

        将常量字符串首字符的地址赋值给字符指针ptr, 字符串常量的值是代表存放字符串常量首字符的储存单元的地址,实质上是一个指向该字符串首字符的指针常量。

笔试题:

#include <stdio.h>
int main()
{char str1[] = "hello world.";char str2[] = "hello world.";const char* str3 = "hello world.";const char* str4 = "hello world.";if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if (str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}
str1 and str2 are not same
str3 and str4 are same

        由于常量字符串不能被修改,所以常量字符串只会在内存中存放一份(只读数据区),当赋值定义时共用该常量字符串。而字符数组与之不同,即使内容相同,也不会共用同一内存空间。

二、指针数组

整型数组——存放整形的数组

字符数组——存放字符的数组

指针数组——存放指针的数组

字符指针数组:

#include <stdio.h>
int main()
{const char* arr[4] = { "abcdef","qwer","hello world","hehe" };int i = 0;for (i = 0; i < 4; i++){printf("%s\n", arr[i]);}return 0;
}
//打印
abcdef
qwer
hello world
hehe

 

 整形指针数组:

#include <stdio.h>
int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 2,3,4,5,6 };int arr3[5] = { 3,4,5,6,7 };int arr4[5] = { 0,0,0,0,0 };int* arr[4] = { arr1,arr2,arr3,arr4 };int i = 0;for (i = 0; i < 4; i++){int j = 0;for (j = 0; j < 5; j++){printf("%d ", arr[i][j]);//printf("%d",*(arr[i]+j));// arr[i] == *(arr + i),与指针数组很像}printf("\n");}return 0;
}
//打印
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
0 0 0 0 0

三、数组指针 

1.数组指针的定义

整形指针——存放整形地址的指针——指向整形的指针——char *

字符指针——存放字符地址的指针——指向字符的指针——int *

数组指针——存放数组地址的指针——指向数组的指针

int main()
{char ch = 'w';char* pc = &ch;int num = 10;int* pi = &num;int arr[10];//pa就是一个数组指针int (*pa)[10] = &arr;return 0;
}

        解释:p先和*结合,说明p是一个指针变量,然后指针指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。(理解)
        这里要注意:[ ] 的优先级要高于*号的,所以必须加上()来保证p先和*结合。

int (*p)[10] = arr;//错误

        这样写是错误写法,是不合理的,因为arr数组名代表数组首元素地址,是int*,而此时p的类型是int(*)[10],两者类型不同 

2.&数组名与数组名

#include <stdio.h>
int main()
{int arr[10] = { 0 };printf("%p\n", arr);printf("%p\n", &arr);return 0;
}

        可以发现数组首元素的地址和数组的地址从值的角度来看是相同的,但它们所代表的意义不同:

        我们知道指针类型不同,指针+1或-1,指针移动的字节数不同,故

#include <stdio.h>
int main()
{int arr[10] = { 0 };printf("arr = %p\n", arr);printf("&arr= %p\n", &arr);//printf("%p\n", &arr[0]);//int*//printf("%p\n", &arr[0]+1);//4printf("arr+1 = %p\n", arr + 1);printf("&arr+1= %p\n", &arr + 1);return 0;
}

        根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是数组的地址,而不是数组首元素的地址,&arr 的类型是: int(*)[10] ,是一种数组指针类型数组地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40
&arr  取出的是数组的地址,只有数组的地址才需要数组指针来接收!
//例如
char arr[5];
char (*pc)[5] = &arr;
// (*pc)代表pc为指针,因为它要接收数组的地址,[5]代表pc指向的是数组,数组有6个元素,每个元素为char

3.数组指针的使用

学习了数组指针,那么数组指针有什么用处,该怎么用呢?

一种鸡肋用法:

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };int(*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p//但是我们一般很少这样写代码int i = 0;for (i = 0; i < 10; i++){printf("%d ", (*p)[i]);}return 0;
}
//打印
1 2 3 4 5 6 7 8 9 10

        p表示数组的地址,它有能力访问所有元素,(*p)表示解引用指针,表示数组首元素的地址,* ( ( *p) + i)表示第几个元素。 

一个数组指针的使用:

#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)
{int i = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){printf("%d ", arr[i][j]);}printf("\n");}
}
void print_arr2(int(*arr)[5], int row, int col)
{int i = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){printf("%d ", arr[i][j]);}printf("\n");}
}
int main()
{int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };print_arr1(arr, 3, 5);//数组名arr,表示首元素的地址//但是二维数组的首元素是二维数组的第一行//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址//可以数组指针来接收print_arr2(arr, 3, 5);return 0;
}

        二维数组是一维数组的一维数组,二维数组名就是第一行的地址,不是a[0][0]的地址,是数组的地址,类型为 int(*)[ ] 。arr + i 是第i行的地址,*(arr + i) 是第i行第一个元素的地址 *( * ( arr + i ) + j) 就是第 i 行第 j 列的元素。

        所以,一个二维数组传参,形参可以是数组指针也可以是二维数组。

在学习了指针数组与数组指针,看下面四个定义,解释定义的类型是什么。

int arr[5];
int* parr1[10];
int(*parr2)[10];
int(*parr3[10])[5];
  1. 整型数组,数组是5个元素
  2. 指针数组, 数组10个元素,每个元素是int *类型
  3. 数组指针,指针指向一个数组,数组是10个元素,每个元素是int
  4. 数组指针数组,parr3先与 [  ]结合,是数组,数组有十个元素,每个元素是 int( * )[ 5 ] 

四、数组参数、指针参数

1.一维数组传参

#include <stdio.h>
void test(int arr[])//ok?    OK    可以不指定数组大小
{}
void test(int arr[10])//ok?    OK
{}
void test(int* arr)//ok?    OK
{}
void test2(int* arr[20])//ok?    OK
{}
void test2(int** arr)//ok?    OK
{}
int main()
{int arr[10] = { 0 };int* arr2[20] = { 0 };test(arr);test2(arr2);//指针数组名,二级指针
}

2.二维数组传参 

void test(int arr[3][5])//ok?    OK
{}
void test(int arr[][])//ok?    NO
{}
void test(int arr[][5])//ok?    OK
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int *arr)//ok?    NO
{}    
void test(int* arr[5])//ok?    NO
{}
void test(int (*arr)[5])//ok?    OK
{}
void test(int **arr)//ok?    NO
{}
int main()
{int arr[3][5] = {0};test(arr);
}

        总结:二维数组传参,函数形参的设计只能省略第一个[ ]的数字,因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素,这样才方便运算。 

分析传过来的是什么,就可判断。

3.一级指针传参

#include <stdio.h>
void print(int* p, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d\n", *(p + i));}
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9 };int* p = arr;int sz = sizeof(arr) / sizeof(arr[0]);//一级指针p,传给函数print(p, sz);return 0;
}

思考:

当一个函数的参数部分为一级指针的时候,函数能接收什么参数? 

  1. 一维数组数组名
  2. 一级指针

4.二级指针传参

#include <stdio.h>
void test(int** ptr)
{printf("num = %d\n", **ptr);
}
int main()
{int n = 10;int* p = &n;int** pp = &p;test(pp);test(&p);return 0;
}
思考:
当函数的参数为二级指针的时候,可以接收什么参数?
  1. 二级指针
  2. 一级指针的地址
  3. 指针数组名
void test(char** p)
{}
int main()
{char c = 'b';char* pc = &c;char** ppc = &pc;char* arr[10];test(&pc);test(ppc);test(arr);//Ok?return 0;
}

五、函数指针

#include <stdio.h>
void test()
{printf("hehe\n");
}
int main()
{printf("%p\n", test);printf("%p\n", &test);return 0;
}

 

输出的是两个地址,这两个地址是 test 函数的地址。&函数名与函数名都是函数的地址.

那我们的函数的地址要想保存起来,怎么保存?

下面我们看代码:

int add(int x, int y)
{return x +y ;
}void test()
{printf("hehe\n");
}int (*pf)(int, int) = &add;下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void *pfun2();
首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针?
答案是:
        pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void
  1. 使用()将pf先于*结合,表示指针,再写指针指向函数的参数类型,返回值类型。
  2. 使用指针访问函数时,还是()将pf与*结合,又此时是函数,函数需要传参,再用()传参。

        其实在调用函数指针时,pf 前面可以不写*,因为定义函数指针后,pf相当于add函数的别名,函数名可以直接使用,那么函数指针也是可以直接使用的,简单地说,前面的*是没有用的,即使是n个*也还是正常使用,但是如果非要使用(*pf)形式的话,必须加()保证优先级,如果*pf不是用括号,那么由于优先级顺序,会造成一些问题。

int (* pf)(int, int) = add;int ret = pf(2, 3);
int ret = (*pf)(2, 3);结果都是5,两式等价

下面,我们来阅读两段有趣的代码:  

//代码1
(*(void (*)())0)();
//代码2
void (*signal(int, void(*)(int)))(int);
  1. 改代码是调用0地址处的函数,是一次函数调用,首先 ( void (*) () ) 0将整型0强转为函数指针类型 void (*)(),再调用0地址处函数 
  2. 该代码是一次函数的声明,声明的函数名字叫 signal,函数 signal 的参数有两个,第一个是int类型参数,第二个是函数指针类型参数,并且该函数指针能指向的那个函数返回类型是void,函数参数是int类型,而signal函数的返回类型是一个函数指针,可以理解为
void (*)(int) signal(int, void (*)(int));

但是在语法上,该代码是错误的,它只是有助于我们理解 

 代码2太复杂,如何简化:

我们知道,typedef可以简化重命名,但是要注意:

typedef void(*)(int) pf_t;

上面这个重命名形式在语法上是错误的,重命名的名字应放在括号里。 (其他重命名规则依旧,这里特殊)

typedef void(*pf_t)(int);pf_t signal(int, pfun_t);

例题:

 定义一个函数指针,指向的函数有两个int形参并且返回一个函数指针,返回的指针指向一个有一个int形参且返回int的函数。

        类比上面第二题,要注意,第二题是函数声明,而该例题是定义函数指针

int (*(*f)(int, int))(int);

 六、函数指针数组

        我们知道,整型指针是指向整型的指针,数组指针是指向数组的指针,其实,函数指针就是指向函数的指针。和学习数组指针一样,学习函数指针我们也需要知道三点:

  • ( )的优先级要高于 * 。
  • 一个变量除去了变量名,便是它的变量类型。
  • 一个指针变量除去了变量名和 * ,便是指针指向的内容的类型。
数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,
比如:
int *arr[10];
//数组的每个元素是int*

那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢? 

int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10];
答案是:parr1
parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢?
是 int (*)() 类型的函数指针。
函数指针数组的用途:转移表

例子:(计算器)  

#include <stdio.h>
int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;do{printf("*************************\n");printf(" 1:add           2:sub \n");printf(" 3:mul           4:div \n");printf("*************************\n");printf("请选择:");scanf("%d", &input);switch (input){case 1:printf("输入操作数:");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("输入操作数:");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("输入操作数:");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("输入操作数:");scanf("%d %d", &x, &y);ret = div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}
使用函数指针数组的实现:
#include <stdio.h>
int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表while (input){printf("*************************\n");printf(" 1:add           2:sub \n");printf(" 3:mul           4:div \n");printf("*************************\n");printf("请选择:");scanf("%d", &input);if ((input <= 4 && input >= 1)){printf("输入操作数:");scanf("%d %d", &x, &y);ret = (*p[input])(x, y);}elseprintf("输入有误\n");printf("ret = %d\n", ret);}return 0;
}

七、指向函数指针数组的指针

        指向函数指针数组的指针是一个指针,指针指向一个数组 ,数组的元素都是函数指针 ;

如何定义?

        既然存在函数指针数组,那么必然存在指向函数指针数组的指针。

	int(*p)(int, int);//函数指针int(*pArr[5])(int, int);//函数指针数组int(*(*pa)[5])(int, int) = &pArr;//指向函数指针数组的指针
void test(const char* str)
{printf("%s\n", str);
}
int main()
{//函数指针pfunvoid (*pfun)(const char*) = test;//函数指针的数组pfunArrvoid (*pfunArr[5])(const char* str);pfunArr[0] = test;//指向函数指针数组pfunArr的指针ppfunArrvoid (*(*ppfunArr)[5])(const char*) = &pfunArr;return 0;
}

八、回调函数

1. 回调函数概念

        回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进 行响应。

首先演示一下qsort函数的使用:

#include <stdio.h>
//qosrt函数的使用者得实现一个比较函数
int int_cmp(const void * p1, const void * p2)
{return (*( int *)p1 - *(int *) p2);
}
int main()
{int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };int i = 0;qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++){printf( "%d ", arr[i]);}printf("\n");return 0;
}

 使用回调函数,模拟实现qsort(采用冒泡的方式)

#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}
void _swap(void* p1, void* p2, int size)
{int i = 0;for (i = 0; i < size; i++){char tmp = *((char*)p1 + i);*((char*)p1 + i) = *((char*)p2 + i);*((char*)p2 + i) = tmp;}
}
void bubble(void* base, int count, int size, int(*cmp)(void*, void*))
{int i = 0;int j = 0;for (i = 0; i < count - 1; i++){for (j = 0; j < count - i - 1; j++){if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0){_swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}
int main()
{int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };//char *arr[] = {"aaaa","dddd","cccc","bbbb"};int i = 0;bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){printf("%d ", arr[i]);}printf("\n");return 0;
}

 九、指针笔试题

笔试题 1
int main()
{int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1);printf( "%d,%d", *(a + 1), *(ptr - 1));return 0;
}
//程序的结果是什么?
笔试题 2
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{int Num;char *pcName;short sDate;char cha[2];short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}
笔试题 3
int main()
{int a[4] = { 1, 2, 3, 4 };int *ptr1 = (int *)(&a + 1);int *ptr2 = (int *)((int)a + 1);printf( "%x,%x", ptr1[-1], *ptr2);return 0;
}
笔试题 4
#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int *p;p = a[0];printf( "%d", p[0]);return 0;
}
笔试题 5
int main()
{int a[5][5];int(*p)[4];p = a;printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);return 0;
}
笔试题 6
int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *ptr1 = (int *)(&aa + 1);int *ptr2 = (int *)(*(aa + 1));printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}
笔试题 7
#include <stdio.h>
int main()
{char *a[] = {"work","at","alibaba"};char**pa = a;pa++;printf("%s\n", *pa);return 0;
}
注意:我们知道char** pa = a;   这里后一个*表示pa是指针第一个*与char结合,表示pa指针指向的对象是char*类型,例如
int *p;
p+1;

p++是跳过前面的一个char类型,同理char** pa,pa++这里跳过一个char*类型

笔试题 8
int main()
{char *c[] = {"ENTER","NEW","POINT","FIRST"};char**cp[] = {c+3,c+2,c+1,c};char***cpp = cp;printf("%s\n", **++cpp);printf("%s\n", *--*++cpp+3);printf("%s\n", *cpp[-2]+3);printf("%s\n", cpp[-1][-1]+1);return 0;
}

关键是画图理解

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HCIP-HarmonyOS Application Developer 习题(三)

1、在JS(JavaScript)Ul框架中&#xff0c;完成对平台层进行抽象&#xff0c;提供抽象接口&#xff0c;对接到系统平台的是哪一层? A. 应用层 B. 前端框架层 C. 引擎层 D. 平台适配层 答案&#xff1a;D 分析&#xff1a;适配层主要完成对平台层进行抽象&#xff0c;提供抽象接…

iOS更新后在IPhone上恢复丢失的文本消息的4种方法

您是否在更新 iPhone 软件后丢失了重要的短信&#xff1f;丢失数据可能会令人沮丧&#xff0c;尤其是当它包含有价值的信息或感性信息时。幸运的是&#xff0c;有一些方法可以在iOS更新后恢复iPhone上丢失的短信。 在这篇博文中&#xff0c;我们将讨论可用于恢复丢失的短信的不…

Edge浏览器 (文本选择)I型光标消失不见问题

Edge浏览器 I型&#xff08;文本选择&#xff09;光标消失不见的问题。 在白色背景中 光标也变成了纯白色&#xff0c;所有都是纯白 也就看不到光标在哪里了&#xff0c;会影响正常使用。 解决方案&#xff1a;把默认的I型光标替换掉 选择一个 beam*.cur , 可以在预览框中查看…

C语言家教记录(六)

导语 本次授课的内容如下&#xff1a;指针&#xff0c;指针和数组 辅助教材为 《C语言程序设计现代方法&#xff08;第2版&#xff09;》 指针 指针变量 计算机按字节划分地址&#xff0c;每个地址访问一个字节 指针变量指向变量的地址&#xff0c;指的是变量第一个字节的…

Leetcode JAVA刷刷站(39)组合总和

一、题目概述 二、思路方向 为了解决这个问题&#xff0c;我们可以使用回溯算法来找到所有可能的组合&#xff0c;使得组合中的数字之和等于目标数 target。因为数组中的元素可以无限制地重复选择&#xff0c;所以在回溯过程中&#xff0c;我们不需要跳过已经选择的元素&#x…

yolov8交互式指定区域行人计数/车辆计数

使用 Ultralytics YOLOv8 进行区域计数 (视频推理) 区域计数是一种用于统计指定区域内物体数量的方法&#xff0c;当考虑多个区域时&#xff0c;这种方法能提供更为精细的分析。这些区域可以根据用户的需求进行调整&#xff0c;并且计数过程能够在实时视频中进行。 目录 装…

Ricardo Milos

目录 一、题目 二、思路 三、payload 四、思考与总结 一、题目 <!-- Challenge --> <form id"ricardo" method"GET"><input name"milos" type"text" class"form-control" placeholder"True" va…

顺丰科技25届秋季校园招聘常见问题答疑及校招网申测评笔试题型分析SHL题库Verify测评

Q&#xff1a;顺丰科技2025届校园招聘面向对象是&#xff1f; A&#xff1a;2025届应届毕业生&#xff0c;毕业时间段为2024年10月1日至2025年9月30日&#xff08;不满足以上毕业时间的同学可以关注顺丰科技社会招聘或实习生招聘&#xff09;。 Q&#xff1a;我可以投递几个岗…

c语言---文件

这一节我准备分三个部分来带领大家了解文件 ——一、有关文件的基础知识 ————二、文件的简单操作 ————————三、文件结束的判定 ————————————四、文件缓冲区 一、文件的基础知识&#xff1a; 首先在了解文件之前&#xff0c;我们需要了解C/C程序内存…

安卓相关环境配置

安卓相关环境配置 偶尔更新。。。 JEB&#xff08;动态调试好用&#xff09; JEB动态调试Smali-真机/模拟器&#xff08;详细&#xff0c;新手必看&#xff09; 夜步城 JADX官网&#xff08;静态分析&#xff09; https://github.com/skylot/jadx/releases/tag/v1.5.0 雷…

MATLAB多项式拟合

订阅专栏或下载资源可以获得源代码:https://download.csdn.net/download/callmeup/89632160 拟合和插值 拟合和插值是两种常见的数学方法,用于以某种方式近似或估计实际数据。 拟合是在给定一组已知数据点的情况下,通过选择一个合适的数学模型来拟合数据。拟合的目标是找到…

民航管理局无人机运营合格证技术详解

1. 证书定义与意义 民航管理局无人机运营合格证&#xff08;以下简称“合格证”&#xff09;是对符合民航法规、规章及标准要求的无人机运营单位或个人进行资质认证的重要证明。该证书旨在确保无人机运营活动的安全、有序进行&#xff0c;保护国家空域安全&#xff0c;维护公众…

Linux·权限与工具-yum与vim

1. Linux软件包管理器 yum 1.1 什么是软件包 在Linux下安装软件&#xff0c;一个通常的办法是下载到程序的源代码&#xff0c;并进行编译&#xff0c;得到可执行程序。但这样做太麻烦了&#xff0c;于是有些人把一些常用的软件提前编译好&#xff0c;做成软件包(可以理解成Win…

超有性价比深度学习卡特斯拉 P100,16G大显存,Stable Diffusion AI 绘画利器

超有性价比深度学习卡特斯拉 P100&#xff0c;16G大显存&#xff0c;Stable Diffusion AI 绘画利器 在当今数字化创作的时代&#xff0c;AI 绘画技术正以惊人的速度发展&#xff0c;为艺术家和创作者们带来了全新的可能性。而要实现高效的 AI 绘画&#xff0c;一款性能卓越的显…

Camera基础知识系列(5)——景深

目录 一. 前言 二. 景深 2.1 弥散圆 2.2 容许弥散圆 2.2 景深(DoF) 三. 如何控制景深 1. 光圈因素 2. 容许弥散圆因素 四. 总结 一. 前言 在摄影中&#xff0c;我们有时会有模糊背景、突出主体的需求&#xff0c;即背景虚化。如下图所示&#xff0c;左边是没有做背景虚化…

序列建模之循环和递归网络 - 递归神经网络篇

序言 在序列建模的广阔领域中&#xff0c;递归神经网络&#xff08; Recursive Neural Network, RNN \text{Recursive Neural Network, RNN} Recursive Neural Network, RNN&#xff09;&#xff0c;注意此处的 RNN \text{RNN} RNN与常用于序列处理的循环神经网络在命名上有所…

打包时未添加camera模块,请参考https://ask.dcloud.net.cn/arss/1ooticle/283

今天在app打包使用的时候突然发现app在拍照上传照片的时候遇到这个问题 遇到这种情况通常是因为app打包的时候manifestjson文件中App模块配置中的Camera&Gallery配置没有打开&#xff0c;点击相应选项勾选即可 然后再上传打包就好了! 哈哈哈好久没写博客了最近太忙了&…

使用 Hugging Face 和 Milvus 构建 RAG 系统

Milvus 是一个广受欢迎的开源向量数据库&#xff0c;为人工智能应用提供高性能和可扩展的向量相似性搜索。在本教程中&#xff0c;我们将向您展示如何使用 Hugging Face 和 Milvus 构建 RAG&#xff08;检索增强生成&#xff09;流程。 RAG 系统将检索系统与 LLM 相结合。该系统…

android13 禁用wifi

总纲 android13 rom 开发总纲说明 目录 1.前言 2.情况分析 3.代码分析 3.1 代码位置1 3.2 代码位置2 3.3 代码位置3 4.代码修改 5. 彩蛋 1.前言 这个文章讲的是,在frameworks里面禁止打开wifi。 2.情况分析 我们打开wifi一般是 public static void turnOnWifi(Co…

x64汇编语言与逆向工程实战指南(四)

目录 1. 数组的存储与遍历1.1 编写数组数据写入内存1.2 汇编循环遍历数组元素 3. Lea指令4. mul指令与imul指令4.1 mul 指令4.2 imul 指令总结 5. div指令5.1 div 指令的基本原理5.2 8 位除法5.3 16 位除法5.3 32 位除法特点和要求 1. 数组的存储与遍历 1.1 编写数组数据写入内…