掘根宝典之c语言#define,#include,#,##,#undef,#if,#ifdef,#elif,#endif,defined函数

news2024/11/23 12:52:07

目录

#define

 #define(宏定义命令)

define与typedef作用域的的区别:

 #define定义宏

注意 

#define 替换规则 

注意 

宏和函数对比 

宏的缺点:

宏和函数的对比 

#运算符

注意点

##运算符

注意点

#include(文件包含命令)

#undef

#if(条件编译)

#ifdef

#ifndef

#elif

#endif

defined函数(与if等结合使用)


#define

 #define(宏定义命令)

格式:#define 标识符 字符串

并不是所有情况下#define所定义的字符串都会被替换,有一种特殊情况:被替换的字符串在""内

代码示例:

#include <stdio.h>

#define MAX 10

int main()
{
    printf("MAX");
}

还有需要注意的一点是,不管是在某个函数内,还是在所有函数之外(不太建议把#define写在函数内),#define作用域都是从定义开始直到整个文件结尾(这一点和typedef就区别很大)

#define(宏定义)----由预处理器来处理

typedef----在编译阶段由编译器处理

代码举例:

#include <stdio.h>

void fun();
int main()
{
    #define MAX int

    MAX a = 10;
    printf("%d", a);
    fun();
}

void fun()
{
    MAX b = 10;
    printf("%d", b);
}

define与typedef作用域的的区别:

typedef:

如果放在所有函数之外,它的作用域就是从它定义开始直到文件尾

如果放在某个函数内,它的作用域就是从它定义开始直到该函数结尾

#define:

不管是在某个函数内,还是在所有函数之外,作用域都是从定义开始直到整个文件结尾 (不管是typedef还是define,其作用域都不会扩展到别的文件,即使是同一个程序的不同文件,也不能互相使用)

这里说下题外话#define叫宏定义,但是在笔者的认识里对声明和定义的理解是:声明不分配内存,定义才分配内存,所以#define虽然名字里面有“定义”两个字,但并不占存储空间(为什么不叫宏声明···)

总结:#define和声明、定义都不同,宏定义不占内存空间,因为宏在预处理阶段就会被替换掉,到了编译的阶段是没有宏存在的,它在预编译阶段就被处理了

 #define定义宏


#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏 (define macro) 

#define 定义宏可分为两种

一种是不带参数的宏定义,这也就是上面提到的使用#define定义标识符
第二种是带参数的宏定义,其定义格式如下

#定义   宏名(参数表)           内容
#define name( parament-list ) stuff


其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中 

#define ADD(a,b) a + b


这个例子定义了一个名为ADD的宏 ,宏的参数有两个 a 和 b,这个宏所要实现的功能是将 a 和 b 相加

如何使用这个宏呢?对比下面两段代码

#define ADD(a,b) (a + b)
 
int main()
{
    int a = 10;
    int b = 20;
    int sum = ADD(a, b);
    printf("%d\n", sum);
    return 0;
}
int ADD(int x, int y)
{
    return x + y;
}
 
int main()
{
    int a = 10;
    int b = 20;
    int sum = ADD(a, b);
    printf("%d\n", sum);
    return 0;
}


其实,宏的使用和我们已知的C语言中的函数类似,都需要进行传参,对比函数版本的求两数之和,可以看到在main函数中,两者的实现方式是几乎一样的,但在具体的实现方式却很不一样

宏定义的程序中,预处理器会将ADD(a,b)替换成 (a + b),.i文件中的代码为

int main()
{
    int a = 10;
    int b = 20;
    int sum = (a + b);
    printf("%d\n", sum);
    return 0;
}


宏定义是将 a + b这样一个求和操作重新命名并置于main函数中,而ADD函数是通过函数调用来实现求和,使用了新的函数栈帧 

注意 

参数列表的左括号必须与name紧邻
如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分 

#define ADD (a,b)


 在这个宏定义中,ADD与()并不直接相连,中间存在空格,因此(a,b)不是宏ADD的参数,而是变成了stuff
考虑下面的代码

#define SQUAREA(x) (x * x)
#define SQUAREB(x) ((x) * (x)) 
 
int main()
{
    int ansa = SQUAREA(3 + 1);
    int ansb = SQUAREB(3 + 1);
 
    printf("%d\n%d\n", ansa, ansb);
 
    return 0;
}


ansa 和 ansb 的输出分别是 7 和 16

这一点似乎出人意料,实际上,宏就是替换,并且是相当直接的替换,上述代码中最重要的一行代码被分别解释为

int ansa = (3 + 1 * 3 + 1)     // 7
int ansb = ((3 + 1) * (3 + 1)) // 16


因此,所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用

#define 替换规则 


在程序中扩展#define定义符号和宏时,需要涉及几个步骤

  • 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换 
  • 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换
  • 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程


注意 

宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归
 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索

宏和函数对比 


一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。那我们平时的一个习惯是: 

把宏名全部大写
函数名不要全部大写 

宏通常被应用于执行简单的运算,比如在两个数中找出较大的一个 

#define MAX(a, b) ((a)>(b)?(a):(b))


那为什么不用函数来完成这个任务?

原因有二: 

用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比函数在程序的规模和速度方面更胜一筹 
更为重要的是函数的参数必须声明为特定的类型。
所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以用于>来比较的类型。宏是类型无关的


宏的缺点:

  • 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序的长度
  • 宏是没法调试的
  • 宏由于类型无关,也就不够严谨
  • 宏可能会带来运算符优先级的问题,导致程容易出现错
  • 宏有时候可以做函数做不到的事情。比如:宏的参数可以出现类型,但是函数做不到
#define MALLOC(num, type)\
(type *)malloc(num * sizeof(type))
...
//使用
MALLOC(10, int);//类型作为参数
//预处理器替换之后:
(int*)malloc(10 * sizeof(int));


宏和函数的对比 

C语言的宏和函数都是用于在程序中重复使用一段代码的工具,但它们有一些不同之处。

宏(Macro)是一种在程序编译阶段进行文本替换的机制。宏定义使用#define关键字,可以将一个表达式、一段语句或者一组语句定义为一个宏。当程序中使用到宏的时候,预处理器会将宏的定义部分替换为实际的代码。宏的优点是代码简洁、执行效率高,但它也有一些缺点,例如宏定义在替换时不会进行类型检查,容易引发一些错误。

函数是一段具有特定功能的代码块,由函数名、参数列表和函数体组成。函数可以被调用多次,它接受参数并返回一个结果。函数的定义和调用发生在程序运行时,而不是编译时,因此函数的执行效率较宏较低。函数的优点是封装性好、可读性强,可以进行类型检查,容错性好。

下面是宏和函数的一些对比:

  1. 参数传递方式:宏在替换时是直接对文本进行替换,不会对参数进行计算,而函数是将参数的值传递给函数体进行计算。

  2. 类型检查:宏在替换时不会进行类型检查,容易引发错误,而函数在定义时可以指定参数的类型,并进行类型检查。

  3. 可读性:函数的代码较宏更可读,因为函数名和参数列表可以直接表达函数的功能,而宏的替换文本可能不够清晰。

  4. 作用域:宏的作用域是全局的,可以在程序的任何地方使用,而函数的作用域可以通过函数的作用域修饰符(如static)进行限制。

  5. 执行效率:宏的代码在编译时就会被替换,因此执行效率较高,而函数的代码在运行时才会被执行,因此执行效率较宏较低。

总的来说,宏适用于一些简单的代码替换,可以提高代码的执行效率,但可读性和容错性较差;函数适用于复杂的代码块,可以提高代码的封装性、可读性和容错性,但执行效率较宏较低。在实际编程中,应根据具体情况选择使用宏还是函数。

#运算符

"#"运算符在C语言中被用作预处理指令的一部分,称为"宏运算符"或"字符串化运算符"。

在C语言中,预处理器是在编译之前对源代码进行处理的工具。预处理器指令以"#"开头,使用一些特殊的预处理指令来操作代码,例如定义宏、包含头文件等。

"#"运算符用于将宏参数转换为字符串常量。当将宏参数包含在双引号内并使用"#"运算符时,它会将参数的值转换为字符串。

以下是一个示例,展示了#运算符的使用方式:

#include <stdio.h>

#define STR(x) #x

int main() {
    int num = 10;
    double pi = 3.14159;
    char* str1 = STR(num);
    char* str2 = STR(pi);

    printf("str1: %s\n", str1);  // 输出结果为 "str1: num"
    printf("str2: %s\n", str2);  // 输出结果为 "str2: pi"

    return 0;
}

在上面的示例中,我们定义了一个宏STR,它接受一个参数并使用#运算符将参数转换为字符串常量。

main函数中,我们声明了一个整型变量num和一个双精度浮点型变量pi,并分别将它们的值赋给str1str2变量。

使用STR宏,我们将变量名转换为字符串常量,并将结果赋值给对应的str变量。

最后,使用printf函数打印str1str2的值,分别输出"str1: num"和"str2: pi"。

请注意,#运算符只能用于将参数转换为字符串,不能用于执行其他计算。它是在预处理阶段进行处理的,而不是在程序运行时进行。

需要注意的是,"#"运算符只能用于预处理指令中,不能直接在C代码中使用。

它的主要作用是在编译之前对源代码进行处理,而不是在运行时执行的运算符。

注意点

在C语言中,#运算符是一种预处理运算符,称为"字符串化运算符"。它的作用是将宏参数转换为一个字符串。

下面是#运算符的注意事项:

  1. #运算符只能用于宏定义中的参数,用于将参数转换为字符串。不能用于变量或表达式。

  2. 使用#运算符时,宏定义中的参数必须用括号括起来,以确保宏调用中传递的参数被正确转换为字符串。例如:

#define STRINGIFY(x) #x

int main() {
    int num = 10;
    printf("%s\n", STRINGIFY(num));  // 输出结果为 "num"
    return 0;
}

在上面的示例中,宏STRINGIFY使用#运算符将参数x转换为字符串。在main函数中,我们声明了一个整型变量num,然后将num作为参数传递给STRINGIFY宏,并使用printf函数打印转换后的结果。输出结果为字符串"num"。

  1. 如果宏参数本身包含.运算符或其他特殊字符,那么#运算符将忽略这些特殊字符,将它们作为普通字符处理。例如:
#define STRINGIFY(x) #x

int main() {
    printf("%s\n", STRINGIFY(x.y));  // 输出结果为 "x.y"
    return 0;
}

在上面的示例中,STRINGIFY宏的参数是x.y,这里的.运算符没有被解释为结构体成员访问符,而是作为普通字符处理。

需要注意的是,#运算符是在预处理阶段进行处理的,它的作用是将宏参数转换为字符串,而不是在程序运行时进行

##运算符

在C语言中,##运算符是一种预处理运算符,称为"连接运算符"或"符号粘贴运算符"。

它的作用是将两个符号连接在一起,形成一个新的符号。

以下是##运算符的使用示例:

#include <stdio.h>

#define CONCAT(a, b) a##b
#define A(n) x##n

int main() {
    int number = 10;
    float value = 3.14;

    int number_value = CONCAT(number, value);  // 将number和value连接在一起形成新的符号number_value

    printf("number_value: %d\n", number_value);  // 输出结果为 10(假设整数和浮点数的大小和表示方式相同)

int A(1)=14;//变成int x1=14;
int A(2)=12;//变成int x2=12;

    return 0;
}

在上面的示例中,我们定义了一个宏CONCAT,它接受两个参数并使用##运算符将两个参数连接在一起。在main函数中,我们声明了一个整型变量number和一个浮点型变量value。然后,使用CONCAT宏将numbervalue连接起来,形成一个新的符号number_value。最后,使用printf函数打印number_value的值,输出结果为10

需要注意的是,##运算符只能用于连接符号,不能用于连接变量或表达式。

它是在预处理阶段进行处理的,而不是在程序运行时进行。

注意点

下面是##运算符的注意事项:

  1. ##运算符只能用于宏定义中,用于将两个参数或符号连接在一起。

  2. ##运算符可以使两个符号连接在一起形成一个新的符号。例如:

#define CONCAT(a, b) a##b

int main() {
    int num = 10;
    printf("%d\n", CONCAT(num, ber));  // 输出结果为 10
    return 0;
}

在上面的示例中,CONCAT宏使用##运算符将参数ab连接在一起形成一个新的符号number,然后在main函数中,我们声明了一个整型变量num,并使用CONCAT宏将字符串number连接在一起,最终打印出变量num的值。

  1. 使用##运算符时,宏定义中的参数不需要用括号括起来。例如:
#define CONCAT(a, b) a##b

int main() {
    printf("%d\n", CONCAT(1, 0));  // 输出结果为 10
    return 0;
}

在上面的示例中,CONCAT宏的参数是10,它们直接通过##运算符连接在一起,最终输出结果为整数10

需要注意的是,##运算符也是在预处理阶段进行处理的,它的作用是将参数或符号连接在一起形成一个新的符号,而不是在程序运行时进行。

#include(文件包含命令)

#include的用法有两种,尖括号<>和双引号""

第一种----尖括号

#include <stdio.h>
  • 1

第二种----双引号

#include "stdio.h"
  • 1

使用尖括号和双引号的区别在于头文件的搜索路径

尖括号:编译器会到系统路径下查找头文件

双引号:编译器会先在当前目录下查找头文件,如果没有找到,再到系统路径下查找

注意事项:

1、一个 #include 命令只能包含一个头文件

2、同一个头文件可以被多次引入,多次引入的效果和一次引入的效果相同,因为头文件在代码层面有防止重复引入的机制

3、头文件包含允许嵌套

(头文件只能包含变量和函数的声明,不能包含定义,否则在多次引入时会引起重复定义错误)

#undef

上文提到#define的作用域是从它声明开始到文件结尾,#undef就是取消之前的宏定义(也就是#define的标识符)

格式:#undef 标识符(注意:如果标识符当前没有被定义成一个宏名称,那么就会忽略该指令)

#include <stdio.h>

#define MAX 10
int main()
{
    printf("%d", MAX);
#undef MAX
#define    MAX 20
    printf("%d", MAX);
}

#if(条件编译)

#if的使用和if else的使用非常相似,一般使用格式如下

#if 整型常量表达式1
程序段1
#elif 整型常量表达式2
程序段2
#else
程序段3
#endif

执行起来就是,如果整形常量表达式为真,则执行程序段1,否则继续往后判断依次类推(注意是整形常量表达式),最后#endif是#if的结束标志

代码示例:

#include "stdio.h"

#define MAX 10
int main()
{
    printf("MAX = %d\n", MAX);

#if    MAX == 10
    printf("MAX已被定义\n");
#else
    printf("MAX未被定义\n");
    #undef MAX
    #define    MAX 20
#endif


    printf("MAX = %d\n", MAX);

    return 0;
}

运行结果:
在这里插入图片描述
代码稍加修改:

#include "stdio.h"

#define MAX 10
int main()
{
#if    MAX == 1
    printf("MAX已被定义\n");
#else
    printf("MAX未被定义\n");
    #undef MAX
    #define    MAX 20
#endif


    printf("MAX = %d\n", MAX);

    return 0;
}

在这里插入图片描述

  • #if命令要求判断条件为整型常量表达式,也就是说表达式中不能包含变量,而且结果必须是整数;而if后面的表达式没有限制,只要符合语法就行,这是#if和if的一个重要区别

#ifdef

#ifdef的作用是判断某个宏是否定义,如果该宏已经定义则执行后面的代码,一般使用格式如下

#ifdef 宏名
程序段1
#else
程序段2
#endif

它的意思是,如果该宏已被定义过,则对程序段1进行编译,否则对程序段2进行编译(这个和上面的#if一样最后都需要#endif),上述格式也可以不用#else,这一点上和if else相同

代码示例:

#include <stdio.h>

#define MAX 10
int main()
{
#ifdef MAX
    printf("MAX已被定义\n");
#else
    printf("MAX未被定义\n");
    #undef MAX
    #define    MAX 20
#endif


    printf("MAX = %d\n", MAX);

    return 0;
}

#ifndef

#ifndef恰好和#ifdef相反

#ifndef 宏名
程序段1
#else
程序段2
#endif

如果该宏未被定义,则对“程序段1”进行编译,否则对“程序段2”进行编译

#include <stdio.h>

#define MAX 10
int main()
{
#ifndef MAX
    printf("MAX未被定义\n");
#else
    printf("MAX已被定义\n");
    #undef MAX
    #define    MAX 20
#endif


    printf("MAX = %d\n", MAX);

    return 0;
}

#elif

#elif相当于if else语句中的else if()语句,需要注意的是该语句是#elif,而不是#elseif

#include <stdio.h>

#define MAX 10
int main()
{
#if MAX==0
    printf("MAX=0");
#elif MAX==10
    printf("MAX=10\n");
#endif

    return 0;
}

#endif

#endif上面已经用过多次了,需要知道的就是#endif是#if, #ifdef, #ifndef这些条件命令的结束标志.这里就不再赘述了

上面说了8种预处理命令,下面再补充一个预处理函数(注意是函数且该函数有返回值)

defined函数(与if等结合使用)

defined函数的作用是判断某个宏是否被定义,若该宏被定义则返回1,否则返回0,该函数经常与#if #elif #else配合使用,一般使用格式为:

defined 宏名

defined (宏名)----(个人建议,还是加上括号比较好)

上文提到有#ifdef、#ifndef来判断宏名是否被定义,乍一看defined有点多余,其实不然,#ifdef和#ifndef仅能一次判断一个宏名,而defined能做到一次判断多个宏名

代码示例:

#include <stdio.h>

#define MAX 10
#define MIN 2
#define AVE 6
int main()
{
#if defined (MAX) && defined (MIN) && defined (AVE)
    printf("三个宏已全部定义\n");
#elif MAX==10
    printf("三个宏未全部定义\n");
#endif

    return 0;
}

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

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

相关文章

“色狼”用英语怎么说?柯桥日常英语,成人英语口语学习

最近有粉丝问我"色狼"英文翻译是啥 首先声明不是"colour wolf"哈 关于“色狼”的英文表达有很多 快和C姐一起来看看吧&#xff01; 1.pervert 这个单词的意思是变态、色狼 是对性变态者最直观的描述 He is such a pervert&#xff01; I saw him lo…

激光在SIC晶圆制造中的应用

碳化硅是一种性能优异的第三代半导体材料&#xff0c;具有光学性能良好、化学惰性大、物理特性优良的特点&#xff0c;包括带隙宽、击穿电压高、热导率高和耐高温性能强等优点&#xff0c;常作为新一代高频、高功率器件的衬底材料&#xff0c;广泛应用在高端制造业领域&#xf…

C++入门项目:通讯录管理系统

文章目录 一、步骤拆分1.系统需求2.显示菜单3.添加联系人4.显示联系人5.删除联系人6.查找联系人7.修改联系人8.清空通讯录9.退出功能 二、完整代码&#xff08;200行&#xff09;三、手把手视频教程 一、步骤拆分 1.系统需求 利用C来实现一个通讯录管理系统&#xff0c;系统中…

C# SwinV2 Stable Diffusion 提示词反推 Onnx Demo

目录 介绍 效果 模型信息 项目 代码 下载 C# SwinV2 Stable Diffusion 提示词反推 Onnx Demo 介绍 模型出处github地址&#xff1a;https://github.com/SmilingWolf/SW-CV-ModelZoo 模型下载地址&#xff1a;https://huggingface.co/SmilingWolf/wd-v1-4-swinv2-tagg…

errno 和 strerror函数

今天写了一个很简单的代码&#xff0c;编译时没啥错误和警告&#xff08;主要编译选项没开启警告&#xff09;&#xff0c;然后运行时居然 segmentation fault&#xff0c;把我给看傻了&#xff0c;代码如下&#xff1a; #include <stdio.h> #include <stdlib.h> …

华为认证网络工程师学习笔记:AAA原理与配置

对于任何网络&#xff0c;用户管理都是最基本的安全管理要求之一。 AAA&#xff08;Authentication, Authorization, and Accounting&#xff09;是一种管理框架&#xff0c;它提供了授权部分用户访问指定资源和记录这些用户操作行为的安全机制。因其具有良好的可扩展性&#…

右值引用(rvalue reference)

定义 C11 引入了右值引用&#xff08;rvalue reference&#xff09;的概念&#xff0c;这是为了支持移动语义&#xff08;move semantics&#xff09;和完美转发&#xff08;perfect forwarding&#xff09;而引入的新特性。右值引用允许我们高效地处理临时对象&#xff0c;避…

运维知识点-hibernate引擎-HQL

HQL有两个主要含义&#xff0c;分别是&#xff1a; HQL&#xff08;Hibernate Query Language&#xff09;是Hibernate查询语言的缩写&#xff0c;它是一种面向对象的查询语言&#xff0c;类似于SQL&#xff0c;但不是去对表和列进行操作&#xff0c;而是面向对象和它们的属性…

Tech.co推荐:小型企业必备的5款财务管理软件

创业不易、守业更难。对于刚起步的小企业来说&#xff0c;财务管理也是拦路虎之一。除了财务团队建设、内部监管的加强&#xff0c;工具使用也必不可少。从趋势上来看&#xff0c;企业的财务数字化转型是必经之路&#xff0c;不过对于小企业来说&#xff0c;在谈数字化转型之前…

STM32 GPIO的几种工作模式

介绍STM32 GPIO的几种工作模式 1、输出模式 STM32的引脚输出有两种方式&#xff1a; 1、推挽输出 2、开漏输出 1.1 推挽输出 当引脚设置为推挽输出时&#xff0c;P-MOS和N-MOS共同配合工作。 当使用HAL库 //该函数的作用就是将P-MOS导通&#xff0c;N-MOS关…

FPGA- RGB_TFT显示屏原理及驱动逻辑

下图是TFT显示屏的显示效果 该显示屏共分为 2 个版本&#xff0c;4.3 寸版本的 TFT4.3’’_V3.0 和 5.0 寸版本的 TFT5.0’’_V3.0。 两者 PCB 背板电路完全相同&#xff0c;接口脚位定义完全相同&#xff0c;接口时序完全相同&#xff0c;仅使用的显示屏 模组尺寸不同。设计两…

chromedriverUnable to obtain driver for chrome using ,selenium找不到chromedriver

1、下载chromedriver chromedriver下载网址&#xff1a;CNPM Binaries Mirror 老版本在&#xff1a;chromedriver/ 较新版本在&#xff1a;chrome-for-testing/ 2、设置了环境变量还是找不到chromedriverUnable to obtain driver for chrome using NoSuchDriverException:…

IDEA修改git提交者的信息

git提交后&#xff0c;idea会记录下提交人的信息&#xff0c;如果不修改提交人信息的话&#xff0c;会有一个默认值。避免每次提交都要填提交人信息&#xff0c;直接设置成自己想要的默认值&#xff0c;该怎么操作&#xff1f; 提交的时候在这里修改提交人信息 避免每次都去设置…

小白优化Oracle的利器”sqltrpt.sql”脚本

SQL调优顾问是Oracle自带的一个功能强大的内部诊断工具&#xff0c;用于对性能不佳的SQL语句给出优化建议。但如果从命令行调用它比较麻烦&#xff0c;幸运的是&#xff0c;Oracle提供了一个方便的内置脚本“sqltrpt.sql”&#xff0c;简化了调用过程。 sqltrpt.sql脚本位于Or…

【论文速读】 | AI驱动修复:漏洞自动化修复的未来

本次分享论文为&#xff1a;AI-powered patching: the future of automated vulnerability fixes 基本信息 原文作者&#xff1a;Jan Nowakowski, Jan Keller 作者单位&#xff1a;Google Security Engineering 关键词&#xff1a;AI, 安全性漏洞, 自动化修复, LLM, sanitiz…

C++初阶篇----类与对象下卷

目录 1.再谈析构函数1.1构造函数体赋值1.2 初始化列表1.3 explicit关键字 2.Static成员2.1概念2.2 特性 3.友元3.1 概念3.2友元函数3.3 友元类 4.内部类4.1 概念 5.匿名对象5.1 概念 6.拷贝对象时的一些编译器优化7.再次理解封装 1.再谈析构函数 1.1构造函数体赋值 在对类的实…

力扣大厂热门面试算法题 - 动态规划

爬梯子、跳跃游戏、最小路径和、杨辉三角、接雨水。每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.05 可通过leetcode所有测试用例。 目录 70. 爬楼梯 解题思路 完整代码 Python Java 55. 跳跃游戏 解题思路 完整代码 Python 代码…

LeetCode每日一题 二叉树的最大深度(二叉树)

题目描述 给定一个二叉树 root &#xff0c;返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3 示例 2&#xff1a; 输入&#xff1a;root [1,nul…

大摩突发:将推出比特币ETF

作者&#xff1a;秦晋 随着比特币ETF愈发火爆&#xff0c;华尔街另一家管理1.3万亿美元资产的大型经纪自营商「摩根士丹利」正在蠢蠢欲动&#xff0c;准备进军比特币ETF。 据彭博社数据显示&#xff0c;目前10只比特币现货ETF在上周三创下单日交易新纪录&#xff0c;成交量超过…

太惊艳了!多微信管理利器,让你事半功倍!

作为现代社交媒体的主要平台之一&#xff0c;微信在商务领域中扮演着重要的角色。为了提高我们的工作效率&#xff0c;微信管理系统应运而生。 这个系统可以同时登录多个微信账号&#xff0c;并进行统一管理。除了便捷的登录管理功能外&#xff0c;微信管理系统还提供了许多实…