指针的进阶——(1)
本次讲解重点:
1、字符指针
2、数组指针
3、指针数组
4、数组传参和指针传参
5、函数指针
关于指针这个知识点的主题,我们在前面已经初级阶段已经对指针有了大致的理解和应用了。我们知道了指针的概念:
1、指针就是地址,但口语中说的指针通常指的是指针变量,指针变量用来存放地址,地址唯一标识一块内存空间。
2、指针的大小是固定的4/8字节(32位平台/64位平台)。
3、指针是有类型的,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。
4、指针的运算。
5、二级指针:存放一级指针变量的地址的变量。
理解:指针变量前的第一个*与变量结合表示它是指针,再往前面所有东西表示这个指针所指向对象的类型。
关于初阶指针有什么不太了解,大家可以点击下方链接学习一遍之后,再来学习进阶。
S6---初阶指针_wangjiushun的博客-CSDN博客
接下来,我们继续探讨指针的高级主题。
1. 字符指针
在指针的类型中我们知道有一种指针类型为字符指针:char*
一般我们使用:让一个字符指针指向一个字符变量
int main()
{char ch = 'a';char* pc = &ch;return 0;
}
还有一种使用方式:让一个字符指针指向一个常量字符串的首字符地址
#include<stdio.h>int main()
{const char* pstr = "abcdef";printf("%s\n", pstr);return 0;
}
代码const char *pstr="abcdef";
很容易让我们误以为是把常量字符串存储到字符指针pstr里了,但是想一想一个字符指针怎么可能放得下7个字节的字符串呢?所以其本质是把字符串abcdef首字符的地址放到了pstr中。
图解:
知识点总结:
1. 常量字符串:
①常量字符串不能被修改:用const修饰(如果修改,程序崩溃);
②常量字符串出现在表达式中时,这个常量字符串的值是首字符的地址。
2. const修饰的常变量:变量pstr不能被修改,但是pstr本质上还是一个变量,所以叫常变量
3. %s-打印字符串,直到遇到'\0'才停止。
有这么一道面试题:
#include<stdio.h>int main()
{char str1[] = "hello bit";char str2[] = "hello bit";const char* str3 = "hello bit";const char* str4 = "hello bit";if (str1 == str2){printf("str1 and str2 are same\n");}else{printf("str1 and str2 are not same\n");}if (str3 == str4){printf("str3 and str4 are same\n");}else{printf("str3 and str4 are not same\n");}return 0;
}
大家猜猜运行的结果。
运行结果:
为什么会这样了?
知识点:
总结:
①(常量字符串,不能被修改)C/C++会把常量字符串存储到单独的一个内存区域,当有几个指针,指向同一个常量字符串的时候,它们实际会指向同一块内存。
②但是用相同的常量字符串去初始化不同的数组的时候,就会开辟不同的内存块。③一个变量对应着一个唯一的空间。
图解:
所以str1和str2不同,str3和str4相同。
2. 指针数组
在初阶指针里我们已经学习一次指针数组,指针数组是一个存放指针的数组。
这里,我们在回顾一下:
整形数组-存放整形的数组;
字符数组-存放字符的数组
指针数组-存放指针(地址)的数组
指针数组的使用:使用一维数组模拟二维数组
代码1:存放字符指针的数组
#include<stdio.h>int main()
{//存放字符指针的数组const char* arr[4] = { "abcd","hello","hehe","wang" };//打印int i = 0;for (i = 0; i < 4; i++){printf("%s\n", arr[i]);}return 0;
}
图解:
代码2:存放整形指针的数组
#include<stdio.h>int main()
{int arr1[4] = { 1,2,3,4 };int arr2[4] = { 2,3,4,5 };int arr3[4] = { 3,4,5,6 };//存放整形指针的数组int* arr[3] = { arr1,arr2,arr3 };//打印int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 4; j++){printf("%d ", *(arr[i] + j));//等价于arr[i][j]}printf("\n");}return 0;
}
图解:
总结:这就是和二维数组一样的,只不过我们是使用指针数组来模拟的。
3. 数组指针
3.1 数组指针的定义
数组指针是指针?还是数组?
答案是:指针。
我们已经熟悉:
整形指针-存放整形地址的指针-指向整形的指针 int*
字符指针-存放字符(字符串)地址的指针-指向字符(字符串)的指针 char*
那数组指针是:存放数组地址的指针-指向数组的指针
代码实例:
int main()
{//整形指针int a = 10;int* pi = &a;//字符指针char ch = 'w';char* pc = &ch;//数组指针int arr[10] = { 0 };//int* pa[10]是这样的吗,但是这不是指针数组,//pa先与[]结合了就是数组,int(*pa)[10] = &arr;return 0;
}
对数组指针的理解:①pa先和*结合,说明pa是一个指针变量,然后指向的是一个大小为10个整形的数组。(即pa是一个指针,指向一个数组的指针,叫做数组指针)
②数组指针后面的[]表示所指向的数组有几个元素
知识点:
①注意:[]的优先级要高于*的,所以必须加上()来保证pa先和*结合。
②指针变量前的第一个*与变量结合表示它是指针,再往前面所有的东西表示这个指针所指向对象的类型。
接下来,我们深入了解数组名和&数组名
3.2 &数组名VS数组名
代码1:打印&数组名和数组名的地址观察
#include<stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//打印数组名地址printf(" arr-->%p\n", arr);//打印&数组名地址printf("&arr-->%p\n", &arr);return 0;
}
运行结果:
运行之后我们发现:&数组名和数组名的地址是一样的。
难道两个是一样的吗?
代码2:&数组名和数组名+1
//代码2:
//数组名-数组首元素的地址
// &数组名-是数组的地址
// 数组首元素的地址和数组的地址从值的角度来看是一样的,但是意义不一样
// 指针的类型决定了指针+-整数的步长,指针解引用操作的时候的权限
//#include<stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf(" arr---->%p\n", arr);//指针的类型:int*printf(" arr+1-->%p\n", arr + 1);//+1,向后跳4个字节printf("&arr---->%p\n", &arr);//指针的类型:int(*)[10]printf("&arr+1-->%p\n", &arr + 1);//+1,向后跳40个字节return 0;
}
运行结果:
图解:
根据上面的代码,我们发现:
数组名-数组首元素的地址
&数组名-是数组的地址
数组首元素的地址和数组的地址从值的角度来看是一样的,但是意义不一样。
知识点:
1. 指针的类型决定了指针+-整数的步长,指针解引用操作的时候的权限。
2. 存储一个数组所需的内存字节数:
①一维数组:总字节数=sizeof(类型)*元素个数
②二维数组:总字节数=sizeof(类型)*行数*列数
3、对二维数组数组名的加深理解:数组名就是二维数组首元素的地址
对于二维数组来说,它的第一行就是它的第一个元素,第二行就是它的第二个元素……即一行是一个元素,二维数组是一个一维数组的数组。
//代码:二维数组的数组名 //二维数组的数组名是首元素地址-->第一行的地址 // 对于二维数组一行是一个元素#include<stdio.h>int main() {int arr[3][4] = { 0 };printf("%p\n", arr);printf("%p\n", arr + 1);//跳过了16个字节return 0; }
运行结果:
上机运行实践,也正是如此:arr+1跳40个字节,刚好是一行。
注意区分:二维数组的第一行第一个元素地址是&arr[0][0],
3.3 数组指针的使用
代码1:一维数组数组指针的使用,但是我们很少这样写代码
//代码1:一维数组数组指针的使用,但是我们很少这样写代码#include<stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//数组指针int(*p)[10] = &arr;//打印数组int i = 0;for (i = 0; i < 10; i++){printf("%d ", (*p)[i]);//*p[i]这种写法的话,p先与[i]结合再解引用}return 0;
}
代码2:二维数组数组指针的使用
#include<stdio.h>void print1(int arr[3][4], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){printf("%d ", arr[i][j]);}printf("\n");}
}void print2(int(*p)[4], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){printf("%d ", *(*(p + i) + j));//等价于(*(p+i))[j],也等价p[i][j]}printf("\n");}
}int main()
{int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };//调用函数打印数组print1(arr, 3, 4);print2(arr, 3, 4);return 0;
}
图解:
学了指针数组和数组指针我们一起回顾并看看下面代码的意思:
int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];
4. 数组参数、指针参数
我们写代码的时候难免要把数组或者指针传给函数,那么函数的参数该如何设计呢?
4.1 一维数组传参
void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int* arr)//ok?
{}
void test2(int* arr[20])//ok?
{}void test2(int* arr[])//ok?
{}
void test2(int** arr)//ok?
{}
int main()
{
int arr[10] = { 0 };
int* arr2[20] = { 0 };
test(arr);
test2(arr2);
}
4.2 二维数组传参
void test(int arr[3][5])//ok?
{}
void test(int arr[][])//ok?
{}
void test(int arr[][5])//ok?
{}
void test(int* arr)//ok?
{}
void test(int* arr[5])//ok?
{}
void test(int(*arr)[5])//ok?
{}
void test(int** arr)//ok?
{}
int main()
{
int arr[3][5] = { 0 };
test(arr);
}
4.3 一级指针传参
思考:当一个函数的参数部分为一级指针的时候,函数能接收什么参数?
答案是:①一级指针变量;②一维数组数组名;③变量地址。
比如:
void test1(int *p)
{}
//test1函数能接收什么参数?
void test2(char* p)
{}
//test2函数能接收什么参数?
void test1(int* p)
{}void test2(char* p)
{}int main()
{//test1函数能接收什么参数?int a = 10;int* pi = &a;int arr[5] = { 0 };test1(pi);//一级指针变量test1(arr);//一位数组数组名test1(&a);//变量地址//test2函数能接收什么参数?char ch = 'w';char* pc = &ch;char arr1[6] = { '\0' };test2(pc);test2(arr1);test2(&ch);return 0;
}
4.4 二级指针传参
思考:当函数的参数为二级指针的时候,函数能接收什么参数?
答案是:①二级指针变量;②指针数组数组名;③一级指针变量地址。
代码实例:
void test(char** p)
{ }
int main()
{char c = 'b';char* pc = &c;char** ppc = &pc;char* arr[10];test(&pc);//一级指针变量地址test(ppc);//二级指针变量test(arr);//指针数组数组名return 0;
}
5、函数指针
我们先打印一下函数的地址:
#include<stdio.h>int Add(int x, int y)
{return x + y;
}int main()
{//打印函数地址printf("%p\n", &Add);printf("%p\n", Add);return 0;
}
运行结果:
从结果我们发现:取函数名和函数名,打印的地址一样。
结论:①取函数名和函数名,都是函数的地址。
那函数的地址是怎么保存的呢?
看下面代码:
#include<stdio.h>int Add(int x, int y)
{return x + y;
}int main()
{//数组指针-指向数组的指针int arr[10] = { 0 };int(*pa)[10] = &arr;//函数指针-指向函数的指针int (*pf)(int, int) = &Add;//pf 是一个存放函数地址的指针变量-函数指针int ret1 = pf(2, 3);//pf是函数地址,Add也是函数地址,所以不用解引用也可以int ret2 = (*pf)(2, 3);//写上*也可以,符合语法,但是需注意带()printf("%d %d\n", ret1, ret2);return 0;
}
类比数组指针,函数指针也是如此要注意带()保证*和变量pf先结合。
使用函数指针找到所指向的函数:
①直接写函数指针:因为函数指针变量存储的就是函数的地址,所以在使用的时候可以不解引用。
②函数指针解引用:解引用其实没必要,这样写就是方便理解。因为pf是指针,指针要找到他所指向的对象(对象函数名就是函数的地址),解引用更容易理解,符合语法的理解。(注意:优先级缘故,如果要解引用,一定要使用()把*和函数指针变量括起来。)
现在我们来看两段有趣的代码:
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
代码1的解读:
int main()
{( *( void(*)() ) 0 )();//分析:// ①void(*)()-->函数指针类型,这个函数是无参的// ②()里面放类型-->强制类型转换// ③( void(*)() ) 0 -->把0强转成这种函数指针类型,// 就是0被当成了函数的地址// ④(*指针变量)-->解引用操作,找到0地址的函数// ⑤最后的()-->调用函数不用传参(因为强转的0函数类型是无参的)////总结:该代码是一次函数调用,调用0地址处的一个函数// 首先代码中将0强转为类型为( void(*)() )的函数指针// 然后去调用0地址处的函数return 0;
}
破题点:从0出发,再开始分析。
代码2的解读:
//函数返回类型是函数指针int main()
{void (*signal(int, void(*)(int))) (int);//分析:①signal没有与*结合,这不是指针// ②signal后有括号()-->signal是函数名// ③函数名括号()里-->函数参数// 第一个参数是int类型,第二个参数是函数指针类型// ④语句最后有;没有函数体-->函数是声明// ⑤函数的声明-->形式:函数返回类型 函数名 (形参列表);// 那剩下的void(*)(int)就是函数返回类型了// //总结:该代码是一次函数的声明// 声明的函数名字叫signal// signal函数的参数有2个,第一个是int类型,第二个是函数指针类型,// 该函数指针能够指向的那个函数的参数是int,返回类型是void。// signal函数的返回类型是一个函数指针,// 该函数指针能够指向的那个函数的参数是int,返回类型是void。//我们能不能这么写?//void(*)(int) signal(int,void(*)(int));//答案是不能这么写,帮助理解可以这么写,但是语法上是错的//函数的返回类型是函数指针是,只能把函数名 (形参列表)移到*的后面。//优化:类型简化--->typedef//函数指针的重命名typedef void(*pf_t)(int);pf_t signal(int, pf_t);return 0;
}
破题点:从signal出发,再开始分析。
知识点:
1、函数返回类型是指针函数时的写法:当函数的返回类型是函数指针时,只能把函数名 (参数列表)移到返回类型这个函数指针的*的后面。
2、指针类型简化(重命名)--->typedef
指针类型重命名,别名写在*的后面并且还要注意操作符的优先级(即*先与别名结合)
本次知识点总结:
1. 字符指针的两种使用:
(1)一般使用:让字符指针指向一个字符变量(字符数组),可通过解引用来访问这个字符变量(字符数组)。
(2)还有一种使用方式:让字符指针指向一个常量字符串的首字符地址。
加油站:
(1)常量字符串:①常量字符串不能被修改:用const修饰;②常量字符串出现在表达式中时,这个常量字符串的值是首字符的地址。
(2)const修饰的常变量:不能被修改。
(3)(常量字符串,不能被修改)C/C++会把常量字符串存储到单独的一个内存区域,当有几个指针,指向同一个常量字符串的时候,他们实际会指向同一块内存。
(4)但是用相同的常量字符串去初始化不同的数组的时候,就会开辟不同的内存块。
(5)一个变量对应着一个唯一的空间。
2. 指针数组
指针数组-存放指针(地址)的数组
回顾数组的创建方式:
type_t arr_name [const_n];
//type_t:是数组的元素类型
//arr_name:数组名
//const_n:常量表达式,用来表示数组中元素个数,即数组的大小(长度)
指针数组的使用:一般是使用一维数组模拟二维数组
3. 数组指针
3.1 数组指针的定义
数组指针-存放数组地址的指针-指向数组的指针
如:int arr[10];
int (*parr)[10]=&arr;//数组指针
对数组指针的理解:
①parr先和*结合,说明是一个指针,前面的int是所指向数组的类型,后面的[]是所指向数组的大小。
②注意:[]的优先级要高于*的,所以必须加上()来保证变量先和*结合。
③指针变量前的第一个*与变量结合表示它是指针,再往前所有的东西表示这个指针所指向对象的类型。
3.2 &数组名和数组名
数组名-数组首元素的地址
&数组名-数组的地址
数组首元素的地址和数组的地址从值的角度来看是一样的,但是意义不一样。
加油站:
(1)指针的类型决定了指针+-整数的步长,指针解引用操作的时候的权限。
(2)存储一个数组所需的内存字节数:
①一维数组:总字节数=sizeof(类型)*元素个数
②二维数组:总字节数=sizeof(类型)*行数*列数
(3)对二维数组数组名的加深理解:
数组名是数组首元素的地址,首元素即第一行的地址;
对于二维数组来说可以看成:一行一个元素(即一维数组),二维数组是一个一维数组的数组
3.3 数组指针的使用-二维数组数组名做实参
4. 数组参数、指针参数
4.1 数组传参
数组名作函数实参,地址传递
形参可写为:
(1)数组形式(注意类型一致,若要标注数组大小:数组大小一致)
①一维数组的大小可省略
②二维数组的大小:只能省略第一维[]的大小,第二维[]的不可省略。因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素(列),这样才方便计算。
(2)指针形式
4.2 一级指针传参
思考:当函数的参数为一级指针的时候,函数能接收什么参数?
答案是:①一级指针变量;②一维数组数组名;③变量地址
4.3二级指针传参
思考:当函数的参数为二级指针的时候,函数能接收什么参数?
答案是:①二级指针变量;②数组指针数组名;③一级指针变量地址
5.函数指针
结论:取函数名和函数名,都是函数的地址。
(1)函数指针怎么写?
类比数组指针,函数指针也是要注意操作符的优先级,所以要带()保证*先和变量结合
(2)对函数指针的理解:变量先与*结合,说明变量是一个指针;然后前面的是所指向函数的返回类型,后面的()是所指向函数的参数列表。
(3)使用函数指针找到所指向的函数:
①直接写函数指针:因为函数指针变量存储的就是函数的地址(函数名也是函数的地址),所以在使用的时候可以不解引用。
②函数指针解引用:解引用其实是没必要的,这样写就是方便理解。因为变量是指针,指针要找到它所指向的对象(对象函数名就是函数的地址),解引用更容易理解,符合语法的理解。(注意:优先级缘故,如果要解引用,一定要使用()把*和指针变量括起来。)
加油站:
①函数返回类型是函数指针时的写法:当函数的返回类型是函数指针时,只能把函数名和(参数列表)移到返回类型这个函数指针的*的后面。
②指针类型简化--->typedef
指针类型重命名,别名写在*的后面并且还要注意操作符的优先级(即*先和别名结合)。
指针进阶的主题并未结束,在下一次文章终结。
有什么不足希望大家指出,我会更加努力写出更好的文章。
相关文章:
指针的进阶——(1)
本次讲解重点: 1、字符指针 2、数组指针 3、指针数组 4、数组传参和指针传参 5、函数指针 关于指针这个知识点的主题,我们在前面已经初级阶段已经对指针有了大致的理解和应用了。我们知道了指针的概念: 1、指针就是地址,但口…...
电商平台的促销活动如何抵御大流量的ddos攻击
每一次活动大促带来的迅猛流量,对技术人而言都是一次严峻考验。如果在活动期间遭受黑产恶意 DDoS 攻击,无疑是雪上加霜。电商的特性是业务常态下通常不会遭受大流量 DDoS 攻击,且对延迟敏感,因此只需要在活动期间按需使用 DDoS 防…...
代码随想录-48-104. 二叉树的最大深度
目录前言题目1.层序迭代思路2. 本题思路分析:3. 算法实现4. pop函数的算法复杂度5. 算法坑点前言 在本科毕设结束后,我开始刷卡哥的“代码随想录”,每天一节。自己的总结笔记均会放在“算法刷题-代码随想录”该专栏下。 代码随想录此题链接 …...
【Vue3源码】第六章 computed的实现
【Vue3源码】第六章 computed的实现 上一章节我们实现了 ref 及其它配套的isRef、unRef 和 proxyRefs API。这一章开始实现computed计算属性。 认识computed 接受一个 getter 函数,返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。…...
Java基础之注解
3.注解 3.1概述【理解】 概述 对我们的程序进行标注和解释 注解和注释的区别 注释: 给程序员看的注解: 给编译器看的 使用注解进行配置配置的优势 代码更加简洁,方便 3.2自定义注解【理解】 格式 public interface 注解名称 { public 属性类型 属性名() default 默认值…...
三、线性表
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 提示:这里可以添加本文要记录的大概内容: 自学JAVA数据结构笔记,跟学视频为:黑马程序员Java数据结构与java算法全套教程…...
C++统计方形
统计方形 内存限制:256 MB 时间限制:1 S 题目描述 有一个n*m方格的棋盘,求其方格包含多少正方形、长方形(此处长方形不包含正方形) 输入格式 输入存在多组测试数据。每组测试数据输入两个整数n,m,数字不超…...
Tina_Linux配网开发指南
OpenRemoved_Tina_Linux_配网_开发指南 1 概述 1.1 编写目的 介绍Allwinner 平台上基于wifimanager-v2.0 的WiFi 配网方式,包括softap(WiFi ap 模式热点配网),soundwave(声波配网),BLE(蓝牙低功耗配网)。 1.2 适用范围 • allwinner 软件平台tina v5.0 版本及以…...
高频面试题|RabbitMQ如何防止消息的重复消费?
一. 前言最近有很多小伙伴开始找工作,在面试时,面试官经常会问我们这样一个题目:RabbitMQ如何防止重复消费?有很多小伙伴这个时候都在想,消息怎么还会重复消费呢???.......所以他们在面试后就跑来问壹哥,针对这个比…...
黑盒测试用例设计方法-边界值分析法
目录 一、边界值定义 二、边界值的考虑 三、边界值的优化 四、边界值的设计用例的步骤 五、案例 六、边界值的类型 一、边界值定义 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下…...
项目风险管理中不可忽视的5个关键点
1、风险意识非常重要 项目经理必须要有风险意识,并不是项目计划做好就万事大吉,而是需要对项目风险进行预判,时刻保持风险意识,及时发现和处理项目风险。 项目风险管理关键:风险意识 2、建立组织风险资产库 寻…...
Linux->进程地址空间
目录 前言: 1. 程序地址空间回顾 2. 进程空间是什么 3. 进程地址空间与内存 4. 进程地址空间和内存的关联 5. 为什么要有进程地址空间 前言: 我们在平时学习的过程当中总是听到栈、堆、代码段等等储存空间,但是这些东西到底是什么&…...
【奶奶看了也不会】AI绘画 Mac安装stable-diffusion-webui绘制AI妹子保姆级教程
1.作品图 2.准备工作 目前网上能搜到的stable-diffusion-webui的安装教程都是Window和Mac M1芯片的,而对于因特尔芯片的文章少之又少,这就导致我们还在用老Intel 芯片的Mac本,看着别人生成美女图片只能眼馋。所以小卷这周末折腾了一天&#…...
基于stm32电梯管理系统设计
基于stm32电梯管理系统设计这里记录一下以前自己做的嵌入式课程设计,报告中的图片和文字太多了,全部一个一个把搬过来太麻烦了,需要完整文本和代码自行q我963160156,也可在微信公众号 *高级嵌入式软件* 里回复 *电梯* 查看完整版文章摘要关键…...
Spring中的FactoryBean 和 BeanFactory、BeanPostProcessor 和BeanFactoryPostProcessor解析
文章目录FactoryBean 和 BeanFactory后置处理器BeanPostProcessor 和 BeanFactoryPostProcessorBeanPostProcessorBeanFactoryPostProcessorFactoryBean 和 BeanFactory BeanFactory接⼝是容器的顶级接⼝,定义了容器的⼀些基础⾏为,负责⽣产和管理Bean的…...
【C++从入门到放弃】类和对象(上)
🧑💻作者: 情话0.0 📝专栏:《C从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢! 类和对…...
什么牌子的蓝牙耳机便宜好用?四款高品质蓝牙耳机推荐
随着时代的发展,蓝牙耳机的使用频率越来越高,不少人外出时除了带手机外,蓝牙耳机也成为了外出必备的数码产品之一。现在的蓝牙耳机品牌众多,什么牌子的蓝牙耳机便宜好用?下面,我来给大家推荐四款高品质的蓝…...
eddsa 算法
信息安全课程设计:eddsa 算法 一、项目要求 使用 C 语言开发;可以实现公私钥生成、签名、认证;只需要手动输入明文,代码会自动生成公私钥、签名、认证;记录公私钥生成、签名、认证的时间;在 VS 上运行&am…...
Xcode Developer Document 开发者文档
总目录 iOS开发笔记目录 从一无所知到入门 文章目录IntroDeveloper Documentation 打开方式菜单栏点击 | 快捷键方式另一种打开方式Intro 2016年我在学校学Java的时候,要查某个Java类/方法的用法还得自己手动下载一种.chm格式的开发文档文件,…...
IntelliJ插件开发教程之新建项目
JetBrains公司系列产品IDEA、WebStrom、PyCharm、CLion、GoLand等都是基于IntelliJ Platform开发而成,掌握IntelliJ插件开发技能便能拥有提升开发效率的终极武器。本教程Demo源码请微信公众号“开发效率”进行获取。阅读原文如果您是JetBrains产品的用户,…...
解决SpringBoot中@RequestBody不能和Multipart同时传递的问题
问题描述 今天在做文件上传的时候,遇到了这么一个错误日志: Resolved[org.springframework.web.HttpMediaTypeNotSupportedException: Content type ‘multipart/form-data;boundary--------------------------771899451541318130280588;charsetUTF-8’…...
【华为OD机试模拟题】用 C++ 实现 - 统计匹配的二元组个数(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明统计匹配的二元组个数题目输入输出描述示例一输入输出说明示例二输入输出说明备注Code使用说明 参加华为od机试,一定要注意不要完全背诵代码&...
Vuex 面试题总结 的历史汇总!
一.vuex是什么?怎么使用?哪种功能场景使用它? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用…...
Redis缓存更新策略与缓存穿透、雪崩等问题的解决
文章目录一、缓存更新策略1、三种策略2、策略选择3、主动更新的方案二、缓存存在的问题1、缓存穿透2、缓存雪崩3、缓存击穿三、解决缓存问题1、自定义分布式锁2、解决缓存穿透问题3、解决缓存击穿问题一、缓存更新策略 1、三种策略 内存淘汰:redis自带的内存淘汰机…...
OSI和TCP/IP网络模型细讲
文章目录一、OSI七层参考模型二、TCP/IP体系结构三、TCP/IP参考模型四、沙漏计时器形状的TCP/IP协议族五、两种国际标准对比相似之处不同之处一、OSI七层参考模型 OSI参考模型共分为7层,低三层面向通信,可用软硬件实现;高三层面向信息处理&am…...
【正点原子FPGA连载】第十九章FreeRtos Hello World实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十九章FreeRto…...
php mysql高校田径运动会成绩管理系统
第一章 引言 1 1.1 选题背景 1 1.2 编写目的 2 1.3 目标 2 1.4 功能需求 3 第二章 开发工具介绍 4 2.1 PHP 4 2.2 APACHE 5 2.3 MYSQL数据库 5 2.4 运行环境 WINDOWS XP 6 2.5 XAMPP 6 2.6 DREAMWEAVE8 6 2.7 EDITPLUS 7 第三章 需求…...
scrum敏捷项目管理软件三款
Leangoo领歌Leangoo是国产的一个项目管理软件,www.leangoo.com , 专门的Scrum敏捷开发工具,看板的管理方式,高度可视化。它支持敏捷开发全流程。从产品路线图-需求-迭代-缺陷-测试-上线。燃尽图,工作量,迭代…...
【项目设计】高并发内存池(二)[高并发内存池整体框架设计|threadcache]
🎇C学习历程:入门 博客主页:一起去看日落吗持续分享博主的C学习历程博主的能力有限,出现错误希望大家不吝赐教分享给大家一句我很喜欢的话: 也许你现在做的事情,暂时看不到成果,但不要忘记&…...
西电编译原理期末核心考点汇总(期末真题+相关知识点)
文章目录前言一、正规式1.1 相关知识点1.1.1 正规式定义1.1.2 辅助定义1.2 历年真题二、二义文法2.1 相关知识点2.1.1 二义性概念2.2 历年考题三、全部短语、直接短语和句柄3.1 相关知识点3.1.1 短语,直接短语和句柄定义3.1.2 短语,直接短语和句柄例题3.…...
爱做网站/百度推广营销
最近我们部门来了一个实习生,天天手里捧着一本《Kotlin从入门到精通》在那儿埋头苦读,等一个月都快过去了,我跑去问他能不能开始接项目了。他非常为难的拿着书和我说他只看了一半,项目代码还没看懂,远远没能到能做项目…...
福建自适应网站建设/北京seo案例
当我们去github上克隆代码仓库的时候,一般有两种选择,一种是https协议,一种是ssh协议。这也是最常用的两种协议了。 HTTPS协议(推荐) 优点: 对新手友好,使用简单,clone的时候只需…...
网站 公司 备案/网络推广的基本渠道
环境: H3C-WX2510H version 7.1.064, Release 5435P02 DEVICE_NAME:WX2510H-PWR DEVICE_SERIAL_NUMBER:219***E000H0 MAC_ADDRESS:58C7***B940 MANUFACTURING_DATE:2021-11-03问题描述: H3C wx2510h无线控制器授权激活出错提示activation file现在不能…...
艺友网站建设/北京官网优化公司
降级策略RT是平均响应时间策略 设置RT的响应时间单位毫秒,RT最大值为4900毫秒,需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rtxxx来配置 需要使用到jmeter测试工具,jmeter下载页面 下载zip包即可 解压后修改配置文件b…...
wordpress首页添加价格/软文写作公司
假设需要交换的两个数为 a, b 使用中间变量 ------------- | a | b | t | ------------- 使用一个中间变量来做媒介来交换,设中间变量为t;则通过 a -> t; b -> a; t -> b 完成了交换,代码如下 var t a; a b; b t; 不使用中间变量…...
wordpress适用linux/十大最免费软件排行榜
版权声明:本文作者靖心。靖空间地址:http://blog.csdn.net/kenden23/,未经本作者同意不得转载。 https://blog.csdn.net/kenden23/article/details/26253133 Problem Description魔法师百小度也有遇到难题的时候—— 如今,百小…...