-
20131012宏定义的补充说明
2013-10-12 00:36:44对于宏定义还要说明以下几点: 1. 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一 种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程 序对它不作任何检查。...对于宏定义还要说明以下几点:
1. 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一
种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程
序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。
2. 宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换。
3. 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作
用域可使用#undef命令。
4.#define 条件编译头文件(.h)可以被头文件或C文件包含;
重复包含(重复定义)由于头文件包含可以嵌套,那么C文件就有可能包含多次同一个头文件,
就可能出现重复定义的问题的。通过条件编译开关来避免重复包含(重复定义)
例如
#ifndef __headerfileXXX__
#define __headerfileXXX__ „ 文件内容„
#endif
-
宏定义和const的用法
2014-09-14 18:12:28define是C语言中提供的宏定义命令,特点具有以下几条: (1)为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率。 (2)用宏定义定义一个统一的函数,这样的话调用不用入栈出栈,对...define是C语言中提供的宏定义命令,特点具有以下几条:
(1)为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率。
(2)用宏定义定义一个统一的函数,这样的话调用不用入栈出栈,对程序的执行速度大有好处。
(3)对于多处用到的常量,用宏的话,不易错,而且容易修改。
(4)对于定义宏"函数",它的"参数"一定要加括号,使用宏的时候,要小心使用 ++ -- 等.
1 #define命令剖析
1.1 #define的概念
#define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。
该命令有两种格式:一种是简单的宏定义,另一种是带参数的宏定义。
(1) 简单的宏定义:
#define <宏名> <字符串>
例: #define PI 3.1415926
(2) 带参数的宏定义
#define <宏名> (<参数表>) <宏体>
例: #define A(x) x
一个标识符被宏定义后,该标识符便是一个宏名。这时,在程序中出现的是宏名,在该程序被编译前,先将宏名用被定义的字符串替换,这称为宏替换,替换后才进行编译,宏替换是简单的替换。
1.2 宏替换发生的时机
为了能够真正理解#define的作用,让我们来了解一下对C语言源程序的处理过程。当我们在一个集成的开发环境如Turbo C中将编写好的源程序进行编译时,实际经过了预处理、编译、汇编和连接几个过程,见图1。
源程序
预处理器
修改后的源程序
编译器
汇编程序
汇编器
可重定位的目标程序
连接器
可执行的目标程序
图1 C语言的编译过程
其中预处理器产生编译器的输出,它实现以下的功能:
(1) 文件包含
可以把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。
(2) 条件编译
预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。
(3) 宏展开
预处理器将源程序文件中出现的对宏的引用展开成相应的宏定义,即本文所说的#define的功能,由预处理器来完成。
经过预处理器处理的源程序与之前的源程序有所有不同,在这个阶段所进行的工作只是纯粹的替换与展开,没有任何计算功能,所以在学习#define命令时只要能真正理解这一点,这样才不会对此命令引起误解并误用。
2 #define使用中的常见问题解析
2.1 简单宏定义使用中出现的问题
在简单宏定义的使用中,当替换文本所表示的字符串为一个表达式时,容易引起误解和误用。如下例:
例1 #define N 2+2
void main()
{
int a=N*N;
printf(“%d”,a);
}
(1) 出现问题:在此程序中存在着宏定义命令,宏N代表的字符串是2+2,在程序中有对宏N的使用,一般认为在读该程序时,容易产生的问题是先求解N为2+2=4,然后在程序中计算a时使用乘法,即N*N=4*4=16,其实该题的结果为8,为什么结果有这么大的偏差?
(2)问题解析:如1节所述,宏展开是在预处理阶段完成的,这个阶段把替换文本只是看作一个字符串,并不会有任何的计算发生,在展开时是在宏N出现的地方 只是简单地使用串2+2来代替N,并不会增添任何的符号,所以对该程序展开后的结果是a=2+2*2+2,计算后=8,这就是宏替换的实质,如何写程序才 能完成结果为16的运算呢?
(3)解决办法:将宏定义写成如下形式
#define N (2+2)
这样就可替换成(2+2)*(2+2)=16注意:宏展开只是原封不动的替换,不会做任何工作。
2.2 带参数的宏定义出现的问题
在带参数的宏定义的使用中,极易引起误解。例如我们需要做个宏替换能求任何数的平方,这就需要使用参数,以便在程序中用实际参数来替换宏定义中的参数。一般容易写成如下形式:
#define area(x) x*x
这在使用中是很容易出现问题的,看如下的程序
void main()
{
int y=area(2+2);
printf(“%d”,y);
}
按理说给的参数是2+2,所得的结果应该为4*4=16,但是错了,因为该程序的实际结果为8,仍然是没能遵循纯粹的简单替换的规则,又是先计算再替换 了,在这道程序里,2+2即为area宏中的参数,应该由它来替换宏定义中的x,即替换成2+2*2+2=8了。那如果遵循(1)中的解决办法,把2+2 括起来,即把宏体中的x括起来,是否可以呢?#define area(x) (x)*(x),对于area(2+2),替换为(2+2)*(2+2)=16,可以解决,但是对于area(2+2)/area(2+2)又会怎么样 呢,有的学生一看到这道题马上给出结果,因为分子分母一样,又错了,还是忘了遵循先替换再计算的规则了,这道题替换后会变为 (2+2)*(2+2)/(2+2)*(2+2)即4*4/4*4按照乘除运算规则,结果为16/4*4=4*4=16,那应该怎么呢?解决方法是在整个 宏体上再加一个括号,即#define area(x) ((x)*(x)),不要觉得这没必要,没有它,是不行的。
要想能够真正使用好宏定义,那么在读别人的程序时,一定要记住先将程序中对宏的使用全部替换成它所代表的字符串,不要自作主张地添加任何其他符号,完全展 开后再进行相应的计算,就不会写错运行结果。如果是自己编程使用宏替换,则在使用简单宏定义时,当字符串中不只一个符号时,加上括号表现出优先级,如果是 带参数的宏定义,则要给宏体中的每个参数加上括号,并在整个宏体上再加一个括号。看到这里,不禁要问,用宏定义这么麻烦,这么容易出错,可不可以摒弃它, 那让我们来看一下在C语言中用宏定义的好处吧。
3 宏定义的优点
(1) 方便程序的修改使用简单宏定义可用宏代替一个在程序中经常使用的常量,这样在将该常量改变时,不用对整个程序进行修改,只修改宏定义的字符串即可,而且当常量比较长时, 我们可以用较短的有意义的标识符来写程序,这样更方便一些。我们所说的常量改变不是在程序运行期间改变,而是在编程期间的修改,举一个大家比较熟悉的例 子,圆周率π是在数学上常用的一个值,有时我们会用3.14来表示,有时也会用3.1415926等,这要看计算所需要的精度,如果我们编制的一个程序中 要多次使用它,那么需要确定一个数值,在本次运行中不改变,但也许后来发现程序所表现的精度有变化,需要改变它的值, 这就需要修改程序中所有的相关数值,这会给我们带来一定的不便,但如果使用宏定义,使用一个标识符来代替,则在修改时只修改宏定义即可,还可以减少输入 3.1415926这样长的数值多次的情况,我们可以如此定义 #define pi 3.1415926,既减少了输入又便于修改,何乐而不为呢?
(2) 提高程序的运行效率 使用带参数的宏定义可完成函数调用的功能,又能减少系统开 销,提高运行效率。正如C语言中所讲,函数的使用可以使程序更加模块化,便于组织,而且可重复利用,但在发生函数调用时,需要保留调用函数的现场,以便子 函数执行结束后能返回继续执行,同样在子函数执行完后要恢复调用函数的现场,这都需要一定的时间,如果子函数执行的操作比较多,这种转换时间开销可以忽 略,但如果子函数完成的功能比较少,甚至于只完成一点操作,如一个乘法语句的操作,则这部分转换开销就相对较大了,但使用带参数的宏定义就不会出现这个问 题,因为它是在预处理阶段即进行了宏展开,在执行时不需要转换,即在当地执行。宏定义可完成简单的操作,但复杂的操作还是要由函数调用来完成,而且宏定义 所占用的目标代码空间相对较大。所以在使用时要依据具体情况来决定是否使用宏定义。
形式参数不能用带引号的字符串替换。
但是,如果在替换文本中,参数名以#作为前缀则结果将被扩展为由 实际参数 替换 此实际参数的带引号的字符串。
例如,可以将它与字符串连接运算结合起来编写一个调试打印宏:
#define dprint(expr) printf(#expr “ = %/n”,expr)
使用语句 dprint(x/y);
调用宏时,该宏将被扩展为:printf(“x/y”“ = %/n”,x/y);
其中的字符串被连接起来了,这样便等价于printf(“x/y = %/n”,x/y);
在实际参数中,每个双引号“ 将被替换为 /” ;反斜杠/将被替换为//,因此替换后的字符串是合法的字符串常量。
预处理运算符 ## 为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与 ## 相邻,则该参数将被实际参数替换,##与前后的空白符将被删除,并对替换后的结果重新扫描。
例如,下面定义的宏paste用于连接两个参数
#define paste(front, back) front ## back
因此,宏调用past(name,1)的结果将建立记号name1.
c语言中没有swap这个函数,C语言不支持重载,也没有模版的概念,所以对于每一种类型,都要写出相应的swap,如
intSwap (int *, int *);
longSwap (long *, long *);
stringSwap (char *, char *);
宏定义swap(t,x,y)以交换t类型的两个参数(要使用程序块结构)。
程序如下:
#include <iostream.h>
#define SWAP(t,x,y) /
{/
temp = *y;/
*y = *x;/
*x = temp;/
}
main()
{
int a = 10, b = 5;
SWAP(int,&a,&b)
cout << a << endl << b<<endl;
}
用/换行,/的意思是说把下一行看作和这行是同一行.换行必须要反斜杠,而且/后面直接回车,不能有空格。 -
C语言_01_宏定义使用技巧
2017-12-08 08:35:15对于底层软件开发的工程师, 对宏定义肯定不陌生吧, 我在写代码的时候就习惯使用宏定义, 代码结构清晰, 修改也及其便捷, 在以下场景时使用宏定义的优势. 1. 防止头文件被重复包含#ifndef MAIN_H #define MAIN_H ........对于底层软件开发的工程师, 对宏定义肯定不陌生吧, 我在写代码的时候就习惯使用宏定义, 代码结构清晰, 修改也及其便捷, 在以下场景时使用宏定义的优势.
1. 防止头文件被重复包含
#ifndef MAIN_H #define MAIN_H ..... //代码部分, 一般为全局变量, 函数声明 #endif
2. 简单函数实现
#define ABS(x) ((x)>=0 ? (x):(-x);) //取绝对值 #define ADD(x,y) ((x)+(y)) //加法 #define MAX(x,y) ((x)>(y) ? (x):(y)) //最大值
3. 获取变量地址
#define PTR(var) ((UINT32*)(void*)&(var))
4. 字节拼字/字拆字节
#define BYTE_TO_WORD(ray) ((word)((ray)[0]*256)+(ray)[1]) //字节拼字 LSB方式 #define WORD_TO_BYTE(ray,val) \ (ray)[0] = ((val)/256); \ (ray)[1] = ((val) & 0xFF) //字拆字节
5. 类型重定义, 使代码跨平台和编译器
typedef unsigned char UINT8; typedef signed char INT8; typedef unsigned short UINT16; typedef signed short INT16; typedef unsigned long int UINT32; typedef signed long int INT32; typedef UINT8 BOOL;
6. 获取成员在结构体中的偏移/所占字节数
#define MEM_OFF(type, field) (((UINT32)&(type *)0)->field) //偏移 #define MEM_SIZE(type, field) (sizeof(type *)0)->field) //所占字节数
7. 获取指定地址上的字节/半字/字
#define ADDR_BYTE(x) (*(UNIT8*)(x)) //字节 #define ADDR_BYTE(x) (*(UNIT16*)(x)) //半字 #define ADDR_WORD(x) (*(UINT32*)(x)) //字
8. 大小写转换
#define WORD_LOW(c) ((c)>='A' && (c)<='Z') ? ((c)+0x20) : (c)) #define WORD_UP(c) ((c)>='a' && (c)<='z') ? ((c)-0x20) : (c))
9. 检查是否是十进制/十六进制
#define DEC_CHK(c) ((c)>='0' && (c)<='9') //十进制 #define HEX_CHK(c) ((c)>='0' && (c)<='9') || \ ((c)>='A' && (c)<='F') || \ ((c)>='a' && (c)<='f') //十六进制
10. 获取半字的高低位
#define WORD_LO(c) (UINT8) ((UINT16)(c) & 0xFF)) //低8位 #define WORD_HI(c) (UINT8) ((UINT16)((c)>>8) & 0xFF)) //高8位
11. 结构体初始化
typedef struct //结构体定义 { uint16_t prescaler; /**< Prescaler. */ uint8_t interrupt_priority; /**< Interrupt priority. */ uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */ bool reliable; /**< Reliable mode flag. */ } nrf_drv_rtc_config_t; #define NRF_DRV_RTC_DEFAULT_CONFIG \ //使用宏初始化结构体成员变量 { \ .prescaler = RTC_FREQ_TO_PRESCALER(RTC_DEFAULT_CONFIG_FREQUENCY), \ .interrupt_priority = RTC_DEFAULT_CONFIG_IRQ_PRIORITY, \ .reliable = RTC_DEFAULT_CONFIG_RELIABLE, \ .tick_latency = RTC_US_TO_TICKS(NRF_MAXIMUM_LATENCY_US, RTC_DEFAULT_CONFIG_FREQUENCY), \ } static nrf_drv_rtc_config_t const m_rtc_config = NRF_DRV_RTC_DEFAULT_CONFIG;
12. 防止溢出
#define OVERFLOW(val) (val = ((val)+1 > (val)) ? (val)+1 : (val))
13. 求数组元素个数
#define ARR_NUM(a) ((sizeof(a)/sizeof(a[0]))
14. 求最接近的倍数值 //常用于内存分配
#define POWER8(x) ((((x)+7)/8)*8)
15. 用于跟踪调试 //ANSI标准(仅限于标准编译器, 非标准编译器可能支持不全或不支持)
__LINE__ //对应 %d 表示当前指令所在行, 是个整型数 __FILE__ //对应 %s 表示当前指令所在文件, 包含完整路径 __DATE__ //对应 %s 包含形式为月/日/年的字符串, 表示源文件被翻译到代码时的日期 __TIME__ //对应 %s 包含源代码翻译到目标代码的时间, 字符串形式为 时:分:秒 __STDC__ //含有十进制常量1, 如果它含有任何其它数,则实现是非标准的
16. 调试使用
#ifdef __DEBUG #define DEBUG_MSG(msg, date) printf(msg); printf("%d%d%d", date, __LINE__, __FILE__) #else #define DEBUG_MSG(msg, date)
17. 防止多次初始化(只能进行一次)
#define NRF_LOG_INTERNAL_FLUSH() \ do { \ while (NRF_LOG_INTERNAL_PROCESS()); \ } while (0)
-
关于C语言define宏定义字符串常量
2017-01-08 14:43:50本人一直以为宏对于字符串的处理也是直接在预处理时进行替换;但是最近在工作中遇到了字符串宏+1的情况;于是彻底的颠覆了以前的思维;于是乎进行测试验证得出以下结果。 /*测试*/ #include #define LUOJIAN ...1.问题由来:
本人一直以为宏对于字符串的处理也是直接在预处理时进行替换;但是最近在工作中遇到了字符串宏+1的情况;于是彻底的颠覆了以前的思维;于是乎进行测试验证得出以下结果。
2.测试代码
/*测试*/ #include<stdio.h> #define HELLO "hello" int main() { printf("%s\n",HELLO+1); return 0 ; }
3.现实的输出结果:
“ello” ;
实际上,宏定义的字符串常量在预编译的时候把HELLO替换成字符串常量(“hello”);所以HELLO+1可以理解为“hello”+1 即常量首地址+1,故输出“ello”. -
cmake取消宏定义_宏的高级用法:XMACRO
2020-12-29 06:32:25使用switch-case/if-else对于条件/分支处理的程序设计,我们惯性地会选择switch-case或者if-else,这也是C语言老师当初教的。以下,我们用一个播放器的例子来说明,要实现的功能如下:收到用户操作播放器命令请求,... -
关于宏定义需要注意的几点
2010-04-22 10:03:33对于宏定义还要说明以下几点: 1) 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。... -
网易笔试题-- 宏定义的那点事
2014-05-07 17:46:00过了很久,现在突然想起了一道网易TTT计划中的一道笔试题,是关于宏定义的,但是对于宏定义很不了解,现在记录一下,大概整理一下思路,不知道对不对,希望大家勿喷。 具体的题目记不大清楚了,大概是根据以下两种... -
iOS --- 总结Objective-C中经常使用的宏定义(持续更新中)
2017-07-18 21:49:00将iOS开发中经常使用的宏定义整理例如以下,仅包括Objective-C。 而对于Swift,不能使用宏,则能够定义全局函数或者extension。请參考博客iOS — 总结Swift中经常使用的全局函数和extension(持续更新中)。 // //... -
python中如何识别宏定义的一撇_Python检测生僻字的实现方法
2020-12-07 14:52:54在实现的过程中,才发现自己对于字符编码、以及 python 内部字符串表示的相关知识的缺乏。在这期间,踩过了不少坑,到最后虽然还有些模糊的地方,但总算有一个总体清晰的了解。在此记录下心得,避免以后在同一个地方... -
宏和函数
2019-02-26 00:37:17在程序中扩展#define定义符号和宏时,需要涉及以下几个步骤: 调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换; 替换文本随后被插入到程序中原来文本的位置,对于宏... -
总结一下宏和函数的区别
2019-03-02 23:43:55宏定义时主要用于以下两方面: 1、简单文本或字符串的替换; 2、宏函数。 对于宏函数,我们可能比较陌生,下面举例来介绍一下宏函数: #define SQUARE(x) ((x)*(x)) int main() { int input... -
总结——宏和函数的区别。
2017-10-23 13:28:00宏定义时主要用于以下两方面: 1、简单文本或字符串的替换; 2、宏函数。 对于宏函数,我们可能比较陌生,下面举例来介绍一下宏函数: #define SQUARE(x) ((x)*(x)) int main() { int in... -
C++宏和枚举
2016-05-12 08:52:00宏 我们的计算器程序,用1234对应加减乘除,对于人阅读很产生一点障碍。隔一个月后再看此代码可能想不起是0123还是1234了,还得去代码中查找,如果能为代表四则运算的四个数...//定义四则运算的宏 #define JIA 1 ... -
offsetof宏的用法
2013-05-25 10:32:08Offsetof()宏 定义:#define offsetof(s,m) (size_t )( &(((s *) 0)->m)) 参数说明:s为结构体名称,m为结构体内某成员; 作用:计算结构体s内成员m相对于结构体起始位置的偏移地址; 以下为某位高手的解说... -
C/C++中宏定义(#define)
2020-12-31 19:48:24#define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用该命令,... -
宏替换的final变量
2019-10-02 16:10:55对于一个final变量阿狸说,不管是类变量 实例变量 局部变量,只要满足以下三个条件,那么这个final变量就不是一个变量了,而是一个直接量. 使用final变量修饰符修饰 在定义该final变量时指定了初始值 该初始值可以在... -
宏的高级应用——X-MACRO
2020-09-13 15:23:26对于条件/分支处理的程序设计,我们惯性地会选择switch-case或者if-else,这也是C语言老师当初教的。以下,我们用一个播放器的例子来说明,要实现的功能如下: 收到用户操作播放器命令请求,如“播放”、“暂停”等... -
EXCEL2007VBA与宏完全剖析 1/4
2012-03-31 14:42:03全书包含27章,详细介绍了以下内容:Excel宏录制器和VBA语法,引用区域,使用用户定义函数,循环和流程控制,RlC1公式,使用VBA自动控制Excel 2007新增功能,事件编程,使用用户窗体,创建图表,实现高级筛选,... -
C++ 类中 关于常量 定义 理解总结 最全攻略
2020-02-14 13:29:12由于#define定义的宏常量是全局的,不能达到目的,于是想当然地觉得应该用const修饰数据成员来实现。const数据成员的确是存在的,但其含义却不是我们所期望的。const数据成员只在某个对象生存期内是常量,而对于整个... -
如何实现在类中定义真正的const成…
2013-12-19 20:46:46由于#define定义的宏常量是全局的,不能达到目的,于是想当然地觉得应该用const修饰数据成员来实现。const数据成员的确是存在的,但其含义却不是我们所期望的。const数据成员只在某个对象生存期内是常量,而对于整个... -
关于由结构体首地址算其内部的一些变量时所用的偏移和CONTAINING_RECORD宏
2013-09-25 22:06:03如果定义一个结构体A,用其定义一个变量a,我们由a访问结构体中变量时,有时候会直接想到用"&a+30"(此时30是偏移字节),事实上并不是在&a上加30,应将&a进行以下强转例如:“(char *)&a+30”,最好是在获得地址后... -
如何实现在类中定义真正的const成员变量
2011-02-28 20:20:00由于#define定义的宏常量是全局的,不能达到目的,于是想当然地觉得应该用const修饰数据成员来实现。const数据成员的确是存在的,但其含义却不是我们所期望的。const数据成员只在某个对象生存期内是常量,而对于整个... -
iOS中对于NSString变量引用计数的分析
2018-08-06 17:10:36为了在测试中打印方便,我们可以简单的定义一个宏: #define MDMLog(str) ({NSString *name = @#str; NSLog(@"%@-->%@ %p, %zd", name, [str class], str, [str retainCount]);}) 以下内容... -
跨平台中对于 自旋锁(spinlock) 的包装
2013-11-02 14:25:13跨平台宏(platform.hpp)的定义参见另一篇博文,当然截取代码实现时可以换成自己习惯的定义。跨平台中条件编译的使用使得代码不是那么容易看,但是还好每个函数只有一两句话自旋锁比互斥量轻量一些,适合使用在轻量... -
跨平台中对于 读写锁(rwlock) 的包装
2013-11-02 14:36:02跨平台宏(platform.hpp)的定义参见另一篇博文,当然截取代码实现时可以换成自己习惯的定义。跨平台中条件编译的使用使得代码不是那么容易看,但是还好每个函数只有一两句话windows/VC下使用系统API实现,其他情况下... -
C语言Define
2017-11-23 19:02:27一.不带参数的宏定义 不带参数的宏定义的格式: #define 标识符 字符或字符串 其中,标识符称为宏名。例如:#define PI 3.1415926 其作用是将宏名PI定义为实数3....对于不带参数的宏定义以及宏替换有以下说明:
-
文件操作所需Jar.zip
-
苏州科技学院《高数》多套期末练习卷(含答案) .pdf
-
杭电OJ 1233 还是畅通工程
-
华为1+X——网络系统建设与运维(中级)
-
nacos客户端双击启动
-
MySQL 性能优化(思路拓展及实操)
-
MySQL NDB Cluster 负载均衡和高可用集群
-
列表(list)方法
-
UVA548 Tree
-
投标方法论
-
5个步进电机硬件设计原理图PCB工程文件资料.zip
-
零基础极简以太坊智能合约开发环境搭建并开发部署
-
NFS 实现高可用(DRBD + heartbeat)
-
20210301resume.zip
-
PowerBI重要外部工具详解
-
MATLAB:图像半色调技术简介
-
信息安全管理与信息安全体系实践.ppt
-
图灵机是什么?一起来看看它的工作原理
-
C++ stl标准库官方链接
-
uniapp之导航栏设置和沉浸式的解决方法