C语言笔记:预处理命令与结构体

  ACM金牌带你零基础直达C语言精通-课程资料

 本笔记属于船说系列课程之一,课程链接:ACM金牌带你零基础直达C语言精通icon-default.png?t=N7T8https://www.bilibili.com/cheese/play/ep159068?csource=private_space_class_null&spm_id_from=333.999.0.0

你也可以选择购买『船说系列课程-年度会员』产品『船票』,畅享一年内无限制学习已上线的所有船说系列课程:船票购买入口icon-default.png?t=N7T8https://www.bilibili.com/cheese/pages/packageCourseDetail?productId=598

做题网站OJ:HZOJ - Online Judge

Leetcode :力扣 (LeetCode) 全球极客挚爱的技术成长平台

 一.认识程序编译过程

第一步:源代码编译成为对象文件,在linux 下对象文件是以.o进行结尾的

在linux系统下命令行中执行

gcc -c 源代码文件名

就可以生成.o对象文件

第二步:如何执行链接阶段生成可执行程序

gcc 生成的.o文件名

执行后可以发现生成了a.out可以执行程序

执行程序:

对于编译和链接过程作用:

编译阶段:

语法错误:

1.语法格式错误:

没有分号:

少一个括号:

或者打错关键词等等;

2.未声明标识符:

b0写成了bo:

如何查看对象文件:

对于前面的大写字母理解:
T是表示函数的定义在当前对象文件中;

U是需要在外部去查找定义的;

printf在系统库中,会自动去链接系统库;

链接阶段:

1.test1.c代码:

#include<stdio.h>

int add(int, int);

int main() {
    int a = 123, b = 456;
    printf("a + b = %d\n", a + b);
    printf("add(%d, %d) = %d\n", a, b, add(a, b));
    return 0;
}

other.c:

#include<stdio.h>

int add(int a, int b) {
    printf("[other.c] this is add function");
    return a + b;
}

makefile文本:

test1:
        gcc -c 1.test1.c
        gcc -c other.c
        gcc other.o 1.test1.c

利用make命令执行:

make 会执行 makefile里面的命令

这里发现1.test1.c中声明了add函数,在other.c中定义了add函数,这里就将1.test1.c链接了other.c,这样1.test1.c中调用了add函数,就不会发现链接阶段的错误,也就是定义缺失的错误。如果在1.test1.c中也实现了add函数,那么也会发生链接错误,也就是定义冲突。

总结:

        记住这两句话就可以:      

二.预处理命令家族

1.#include 头文件:

 

预处理命令都以#开头

对于在编译阶段之前还有一个阶段叫预处理阶段:

对于编译阶段检查的是待编译源码的错误

通过预处理阶段,待编译阶段会将#include中的内容和对应的功能作用会处理掉,变为待编译源码中的内容。

下面是代码演示:

5.pre_procesing.c

#include<stdio.h>

int main() {
    printf("hello world");

    return 0;
}

 然后执行一个命令:
gcc -E 源代码文件名 > 定向文件

        这句话的意思就是将5.pre_processing.c源代码,显示他的待编译源码,然后再将输出的内容重定向到output.c文件中

        然后在output.c文件中可以看到许多在我们的源代码没有的内容,那就是#include <stdio.h>头文件替换的内容。

        其实简单来说#include 做的就是复制和粘贴。

下面是对#include的作用展示:

#include <stdio.h>
//这里包含了一个头文件def_a_b.c
#include "def_a_b.c"

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

那么这里包含了def_a_b.c,就需要写源代码:
 

int a = 123, b = 456;

然后进行查看他的待编译源码:

然后在待编译源码中可以看到:

第二行有int a, int b 的定义,以及赋值,也就是def_a_b.c中的那句代码,可以发现#include 做的就是粘贴和复制

编译后执行,发现是可以的;

对于#include <> 和 #Include "" 区别是,<>是在默认查找路径进行查找,""是在当前文件夹进行查找。

如何将自己的头文件添加到默认路径

需要执行的代码:

#include <stdio.h>
#include <def_a_b.c>


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

这局命令的意思就是将 ./(当前目录) 添加到默认路径,然后在对test.c进行编译。然后执行代码:

对于C语言有一个人文规定:

.c后缀为源文件

.h后缀为头文件


2.宏定义(#define)

程序展示宏定义的用法:

#include<stdio.h>

#define PI 3.1415926
//这里为什么需要在(a) * (b),这里每个变量都要加上()
//应为define的作用只是替换
//如果没有(), 对应下面的S(3 + 7, 4); 替换的结果就是3 + 7 * 4
//最终结果是31, 不是我们想要的(3 + 7) * 4的结果40
#define S(a, b) (a) * (b)
#define s(a, b) a * b
//定义多行宏时需要在每行末尾加上\进行续尾
#define P(a) {\
    printf("define P : %d\n", a);\
}

int main() {
    printf("PI = %lf\n", PI);
    printf("S(3, 4) = %d\n", S(3, 4));
    printf("S(3 + 7, 4) = %d\n", S(3 + 7, 4));
    //这里利用宏定义替换
    //就相当于定义了一个int类型的指针p 
    s(int, p);
    int a = 123;
    p = &a;
    P(*p);
    return 0;
}

待编译源码:


执行结果:

编译器中内置宏:

在程序中的使用方法:

#include<stdio.h>

int main() {
    printf("__DATE__ = %s\n", __DATE__);
    printf("__TIME__ = %s\n", __TIME__);
    printf("__LINE__ = %d\n", __LINE__);
    printf("__FILE__ = %s\n", __FILE__);
    printf("__func__ = %s\n", __func__);
    printf("__PRETTY_FUNCTION__ = %s\n", __PRETTY_FUNCTION__);
    return 0;
}

执行结果:

宏定义中#和##的作用:

#的作用:将#后面的内容字符串化

##的作用: 将两个内容连接到一起,比如a##b,将a和b连接到一起

下面的代码演示:

#include<stdio.h>

#define STR(n) #n
//这里的宏表示 执行func函数,并且打印func函数名以表func函数执行结束
#define RUN(func) {\
    func;\
    printf("%s done\n", #func);\
}

//这个宏定义的作用是将a和b进行连接到一起
#define CAT(a, b) a##b
void test1() {
    printf("this is test1()\n");
    return ;
}

void test2(int a, int b) {
    printf("this is test2(): a = %d, b = %d\n", a, b);
    return ;
}

int main() {
    printf("%s\n", STR(hello));
    RUN(test1());
    RUN(test2(1, 2));
    int n10 = 123, n11 = 456;
    CAT(n, 10) = 789;
    printf("n10 = %d, n11 = %d\n", n10, n11);
    return 0;
}

源代码截图:

待编译源码:

可以发现,之前用宏定义的代码全部被替换了。

执行结果:

3.条件编译(#if)

对于#ifdef的使用:

定义了DEBUG宏情况

#include<stdio.h>

#define DEBUG

#ifdef DEBUG
int a = 1;
#else 
int a = 2;
#endif

int main() {
    printf("a = %d\n", a);

    return 0;
}

待编译代码:

可以发现不满足的地方的代码被#ifdef裁掉了。

执行结果也显而易见了:

如果没有定义DEBUG宏,那么被裁掉的地方会是int a = 1;留下的是int a = 2;

如何在执行命令行阶段去定义宏:

gcc -D宏的名字   文件名

现在10.ifdef.c是没有定义DEBUG宏的。

通过句命令就可以在编译过程中定义DEBUG宏

执行结果:就是

三.  结构体

结构体(Struct)是一种在编程语言中用于组织和存储多个相关数据项的复合数据类型。它允许开发者将不同类型的数据项组合在一起,以便于在程序中一起操作和管理。

结构体通常由多个成员变量(也称为字段或属性)组成,每个成员变量可以是不同的数据类型,例如整数、浮点数、字符、数组、指针等。

        图中左边是结构体的定义,右边是结构体的内存图。

对于结构体定义和使用:

#include <stdio.h>
#include <string.h>

//定义结构体需要用struct关键字
typedef struct person {
    char name[20];
    int age;
    char gender;
    float height;
} person;//在前面加上typedef,就可以在最后定义别名,在下方定义结构体变量时,就可以用别名来定义

void output(struct person *p) {
    printf("use pointer p (%s, %d, %c, %f)\n", 
           p->name, 
           p->age, 
           p->gender, 
           p->height);
    return ;
}
//这个函数的作用是将结构体变量所占空间,转换为buff字符串来可见
//第一个参数用来转换的buff字符串
//第二个参数是结构体起始变量地址
//第三个参数是那个结构体变量的起始地址
//第四个参数是这个结构体变量的结束地址
//第五个参数替换的字符
void set_buff(char *buff, void *head, void *begin, void *end, char ch) {
    //循环判断条件, 当起始位置等于结束位置时结束
    while (begin != end) {
        //这里变量的起始位置减去结构体起始的位置可以得到索引下标
        buff[begin - head] = ch;
        begin += 1;
    }
    return ;
}

void output_person() {
    //开person结构体个大小的字符串
    int n = sizeof(struct person), len = 0;
    char buf[n];
    //初始化字符串内容为.
    for (int i = 0; i < n; i++) buf[i] = '.';
    //打印对应位置索引
    for (int i = 0; i < n; i++) {
        len += printf("%3d", i);
    }
    printf("\n");
    //间隔符
    for (int i = 0; i < len; i++) printf("-");
    printf("\n");
    //定义一个结构体变量
    struct person hug;
    //name有20个字节大小所以从起始位置到结尾有20,并用'n'表示所占位置
    set_buff(buf, hug.name, hug.name, 20 + (void *)hug.name, 'n');
    set_buff(buf, hug.name, &hug.age, 4 + (void *)&hug.age, 'a');
    set_buff(buf, hug.name, &hug.gender, 1 + (void *)&hug.gender, 'g');
    set_buff(buf, hug.name, &hug.height, 4 + (void *)&hug.height, 'h');
    for (int i = 0; i < n; i++) {
        printf("%3c", buf[i]);
    }
    printf("\n");
    return ;
}

int main() {
    //定义结构体变量, 必须在前面加上struct关键字
    //并初始化结构体中的变量
    struct person hug = {"zhang san", 18, 'm', 2.1};
    //利用结构体别名来定义结构体变量
    person su = {"Su", 25, 'm', 1.6};
    //hug.name这种以.的方式进行访问结构体中的变量叫做直接访问
    printf("(%s, %d, %c, %f)\n", hug.name, hug.age, hug.gender, hug.height);
    //通过结构体指针访问结构体变量的方式叫做间接访问
    output(&hug);
    output(&su);
    //查看person结构体占用的字节数
    printf("sizeof(struct person) =%lu\n", sizeof(struct person));
    //执行一个方法,标记每个结构体变量的在这32个字节中的位置
     output_person();
    return 0;
}

执行结果:

可以发现,结构体对应的内存大小不是所有变量对应字节大小进行相加来得到的,在下面的结构体内存对齐规则会讲到,为什么是这样。

结构体内存对齐规则:

对于刚才代码的结构体进行分析:

这张图说明了1和2两点

然后第3点:

可以发现每个变量的起始位置分别是:
0,20,24,28是可以整除最大对齐值4的

因为25-27是无法整除最大对齐值4的所以,25-27是空的。

对于这个图只是方便理解,计算机底层并不是这样去申请空间。

下面的3个结构体分别对应的大小是:


struct A : 12字节

struct B:8字节

struct C:7字节

第一个很好理解;

第二个最大对齐值是4,先存char然后还有3个字节空间,然后short是两个字节可以存储,斌且要存储在能整除他的位置上,然后没有空间无法存int类型,需要重新申请一个空间,然后来存储int类型,最终是8字节。

第三个有一句代码#pragma pack(1),那么最大对齐值就被限制为1,所以就一个字节空间的开辟来进行存储,最后结果为7字节。

四.联合体

对于下面联合体所占空间只有4个字节大小:

对于上面的联合体代码是实现:

#include<stdio.h>

#define P(a, format) {\
    printf("%s = " format "\n", #a, a);\
}

union A {
    struct {
        unsigned char byte1;
        unsigned char byte2;
        unsigned char byte3;
        unsigned char byte4;
    } bytes;
    unsigned int number;
};

int main() {
    union A a;
    a.number = 0x61626364;
    P(a.number, "%x");
    P(a.bytes.byte1, "%x");
    P(a.bytes.byte2, "%x");
    P(a.bytes.byte3, "%x");
    P(a.bytes.byte4, "%x");
    P(sizeof(union A), "%lu");
    P(&a.number, "%p");
    P(&a.bytes.byte1, "%p");
    P(&a.bytes.byte2, "%p");
    P(&a.bytes.byte3, "%p");
    P(&a.bytes.byte4, "%p");
    return 0;
}

执行结果:

可以发现,对number进行赋值后,对应结构体中的byte1~4的值也是对应的值;说明他们是公用的一块内存区域。对于为什么是倒过来存的是因为是小端系统,数字的地位存储在内存的低位。

不仅number可以对对应区域进行赋值和取值,bytes也可以。

五.枚举类型

如何运用枚举类型:

#include<stdio.h>
#define P(a, format) {\
    printf("%s = " format "\n", #a, a);\
}

//从上往下进行自增+1
enum Number {
    zero,
    one,
    two = 10,
    three,
    four
};

enum FUNC_DATA {

#ifdef TEST1
    FUNC_test1,
#endif
#ifdef TEST2
    FUNC_test2,
#endif
#ifdef TEST3
    FUNC_test3,
#endif
#ifdef TEST4
    FUNC_test4,
#endif
    //如果上面存在一个函数,那么FUNC_MAX 就会+1
    //说明有存在几个函数
    FUNC_MAX
};

//利用宏定义,定义函数
#define DEFINE_FUNC(name)\
void name() {\
    printf("this function : %s\n", #name);\
}

DEFINE_FUNC(test1);
DEFINE_FUNC(test2);
DEFINE_FUNC(test3);
DEFINE_FUNC(test4);

//函数指针数组
//利用#ifdef来进行对函数指针数组进行存储 
void (*func_arr[FUNC_MAX])() = {
#ifdef TEST1
    test1,
#endif
#ifdef TEST2
    test2,
#endif
#ifdef TEST3
    test3,
#endif
#ifdef TEST4
    test4,
#endif
};

int main() {
    for (int i = 0; i < FUNC_MAX; i++) {
        func_arr[i]();
    }
    enum Number a;
    a = zero;
    P(a, "%d");
    a = one;
    P(a, "%d");
    a = two;
    P(a, "%d");
    a = three;
    P(a, "%d");
    a = four;
    P(a, "%d");
    return 0;
}

如何进行对宏TEST进行添加

这个在#if中讲过,执行命令:

gcc后面可以跟多个参数添加宏

执行结果:

如何使用printf打印有颜色的字体

程序中如何运用:

#include<stdio.h>

//对于这份代码,主要的是宏定义和枚举类型的运用
//大部分都是宏定义的内容,所以对于代码不懂,可以再回看关于宏定义的内容

#ifdef plana
//利用宏定义进行封装collor工具
#define COLLOR(msg, code) "\033[1;" #code "m" msg "\033[0m"
#define RED(msg) COLLOR(msg, 31)
#define GREEN(msg) COLLOR(msg, 32)
#define YELLOW(msg) COLLOR(msg, 33)
#define BLUE(msg) COLLOR(msg, 34)



int main() {
    //格式为\033[格式控制然后用;进行分隔跟上一个m,然后m后跟上需要打印的内容
    //最后\033[0m表示讲字体格式和颜色进行初始化
    //不然后面的字体都会变为你改变的颜色和格式
    printf("\033[1;32;43mhello world\n\033[0m");
    //使用宏定义进行输出带有演示的字体
    printf(RED("hello world\n"));
    printf(GREEN("hello world\n"));
    printf(YELLOW("hello world\n"));
    printf(BLUE("hello world\n"));

    return 0;
}


#else 

//利用枚举类型进行封装color工具
enum COLOR_CODE {
    RED =31,
    GREEN,
    YELLOW,
    BLUE
};

//利用宏定义封装输出信息
#define COLOR_SET "\033[1;%dm"
#define COLOR_END "\033[0m"


int main() {
    printf(COLOR_SET "hello color plan b\n" COLOR_END, RED);
    printf(COLOR_SET "hello color plan b\n" COLOR_END, GREEN);
    printf(COLOR_SET "hello color plan b\n" COLOR_END, YELLOW);
    printf(COLOR_SET "hello color plan b\n" COLOR_END, BLUE);
    //如果不懂下面的代码,可以再回看关于宏定义的内容
    printf(
        COLOR_SET "hello "
        COLOR_SET "color "
        COLOR_SET "plan "
        COLOR_SET "b"
        "\n"
        COLOR_END,
        RED,
        GREEN,
        YELLOW,
        BLUE
        );
    return 0;
}

#endif 

实现plana的方法:

执行结果:

实现planb的方法:

六.位域相关概念

直接程序理解:

include<stdio.h>

#define P(a, format) {\
    printf("%s = " format "\n", #a, a);\
}

struct A {
    //这里用到了无符号整形,有可能输出的结果都为-1,所以需要用到无符号
    unsigned int a:1;//这里的代码说明a变量只用二进制的一位
    unsigned int b:2;//同理
    unsigned int c:3;
    //一共用了6位二进制
};


int main() {
    //由于struct A最大对齐值的4
    //所以struct A占4字节
    P(sizeof(struct A), "%lu");//4
    struct A p;
    p.a = 15;
    p.b = 15;
    p.c = 15;
    //如果超出了占位的取值范围,那么只取后面几位,也就是低位
    P(p.a, "%d");//因为只占用一位,所以对应二进制是1,输出结果结果为1
    P(p.b, "%d");//因为只占用两位,所以对应二进制是11,输出结果结果为3
    P(p.c, "%d");//因为只占用三位,所以对应二进制是111,输出结果结果为7
    return 0;
}

在编译过程中有waring,只是警告的意思,但是依旧可以运行程序

执行结果:

章节小结:

        理解程序的编译过程,在那些阶段会发现什么错误,以及每个阶段的作用是什么;

        对于预处理,理解头文件是如何进行工作的,在后续的项目阶段会用上;对于宏定义一定要学会如何去使用,这样在以后编码的过程中可减少很多代码量。

        结构体在后续数据结构中,是经常会用到的内容,基本每个结构都会用到结构体进行去封装,对于结构体内存的对齐规则一定要去理解其中是如何进行对齐的,这个内容在考试会考到。

        联合体明白如何使用,知道这个东西,并且知道内存是如何进行公用就可以。

        枚举类型学会后,在以后的编码过程中,学会去运用它,然编码的可读性和灵活性变得更高。

        最后加油,看到这里你已经超过百分之95的人了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

字符驱动程序-LCD驱动开发

一、驱动程序的框架 总共分为五步&#xff1a; 1、自己设定或者系统分配一个主设备号 2、创建一个file_operations结构体 这个结构体中有操作硬件的函数&#xff0c;比如drv_open、drv_read 3、写一个注册设备驱动函数 需要register_chrdev(major,name,结构体)&#xff0…

文件一键加水印的软件叫什么

答&#xff1a;文件一键加水印的软件叫“域智盾软件”。 域智盾作为一款专为企业内网信息安全保驾护航的领先软件&#xff0c;以其卓越的文件加密技术和自动添加水印功能为核心亮点&#xff0c;为企业提供了强大的数据安全保障和严谨的内部信息追踪机制。 【文件加密功能】 高…

C语言数据结构易错知识点(4)(二叉树、分治思想)

1.二叉树的特点&#xff1a;和顺序表、链表有所差异的是&#xff0c;二叉树并不主要用于存储数据&#xff0c;它多用于数据的筛选、处理等操作。二叉树内核是分治思想&#xff0c;对递归运用的要求很高&#xff0c;这在二叉树的各种接口的实现上我们都能有所体会。 2.最小子问…

Linux系统 安装docker

安装&#xff1a; 1、Docker要求CentOS系统的内核版本高于 3.10 &#xff0c;通过 uname -r 命令查看你当前的内核版本是否支持安账docker 2、更新yum包&#xff1a; sudo yum -y update 3、安装需要的软件包&#xff0c;yum-util 提供yum-config-manager功能&#xff0c;另外…

Excel双击单元格后弹窗输入日期

Step1. 在VBE界面新建一个窗体(Userform1),在窗体的工具箱的空白处右键,选中添加附件,勾选Calendar control 8.0,即可完成日历的添加。 PS:遗憾的是, Office 64 位没有官方的日期选择器控件。唯一的解决方案是使用Excel 的第三方日历。 参考链接:How to insert calen…

多图回顾|MoonBit 首场线下 MeetUp 回顾

3 月 23 日&#xff0c;MoonBit 首场线下 MeetUp 活动在深圳顺利举办。 在首场 MoonBit 线下 MeetUp 活动中&#xff0c;五位行业内的知名专家带来了四个以探索国产基础软件新发展为主题的精彩内容分享&#xff01; 一起来看看嘉宾们带来了哪些行业内的最新思考吧&#xff01; …

推荐一种Bean注入方式——开发经验

我们都知道三种Bean注入的方式分别是属性注入&#xff0c;setter方法注入&#xff0c;构造器注入。这三种Bean注入的方式各有优缺点&#xff0c;但是相对来说更推荐使用构造器注入的方式。 1、构造器注入的优缺点 优点&#xff1a; 1、可以注入不可变对象 因为构造方法注入是…

【MATLAB源码-第168期】基于matlab的布谷鸟优化算法(COA)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 布谷鸟优化算法&#xff08;Cuckoo Optimization Algorithm, COA&#xff09;是一种启发式搜索算法&#xff0c;其设计灵感源自于布谷鸟的独特生活习性&#xff0c;尤其是它们的寄生繁殖行为。该算法通过模拟布谷鸟在自然界中…

Unity类银河恶魔城学习记录11-3 p105 Inventory UI源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_itemSlot.cs using System.Collections; using System.Collections.Gen…

马上入局:2024年阿里云服务器优惠价格,刷新你的认知!

2024年阿里云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新的云服务器优惠券…

【第二部分--Python之基础】

一、初识 开发语言&#xff1a; 高级语言&#xff1a;Python Java PHP C# Go Ruby C ... > 字节码 低级语言&#xff1a;C 汇编 > 机器码 …

C++中atan和atan2

atan和atan2 两者都在cmath函数中。 atan std::atan(1. / 1.) * 180 / M_PI // 45 deg std::atan(-1. / -1.) * 180 / M_PI // 45 deg atan2 std::atan2(1., 1.) * 180 / M_PI // 45 std::atan2(-1., -1.) * 180 / M_PI // -135 区别 atan值域[-M_PI / 2., M_PI / 2.] a…

【Windows驱动篇】解决Windows驱动更新导致AMD Software软件无法正常启动问题

【Windows驱动篇】解决Windows驱动更新导致AMD Software软件无法正常启动问题 【操作可能有风险&#xff0c;请提前做好数据备份&#xff0c;设置系统还原点等&#xff0c;防止系统出现问题&#xff01;&#xff01;&#xff01;】 【操作可能有风险&#xff0c;请提前做好数…

达梦数据库命令行安装+命令行创建实例

首先创建dmdba用户 groupadd dminstall useradd -g dminstall dmdba sudo passwd dmdba 修改dmdba的权限 cd /etc/security/ limits.d 增加两行代码 dmdba soft nofile 65536 dmdba hard nofile 65536 创建安装文件夹 授权dmdba mkdir -p /app/dbDB8 mkdir installDa…

redis实际应用场景及并发问题的解决

业务场景 接下来要模拟的业务场景: 每当被普通攻击的时候&#xff0c;有千分之三的概率掉落金币&#xff0c;每回合最多爆出两个金币。 1.每个回合只有15秒。 2.每次普通攻击的时间间隔是0.5s 3.这个服务是一个集群&#xff08;这个要求暂时不实现&#xff09; 编写接口&…

代码随想录算法训练营第三十四天 |1005. K 次取反后最大化的数组和 、134. 加油站、135. 分发糖果

代码随想录算法训练营第三十四天 |1005. K 次取反后最大化的数组和 、134. 加油站、135. 分发糖果 1005. K 次取反后最大化的数组和题目解法 134. 加油站题目解法 135. 分发糖果题目解法 感悟 1005. K 次取反后最大化的数组和 题目 解法 考虑绝对值 class Solution { public…

libVLC 视频裁剪

使用 libVLC 进行视频裁剪并不是直接支持的功能&#xff0c;因为 libVLC 主要是一个媒体播放库。然而&#xff0c;你可以通过调整播放窗口的大小和设置视频输出的区域来实现一种“视觉上的裁剪”。这意味着视频本身并没有被修改&#xff0c;但可以控制显示给用户的视频区域。 …

【OJ】动归练习二

个人主页 &#xff1a; zxctscl 如有转载请先通知 题目 1. 91.解码方法1.1 分析1.2 代码 2. 62.不同路径2.1 分析2.2 代码 3. 63.不同路径 II3.1 分析3.2 代码 1. 91.解码方法 1.1 分析 题目所述就是把一串数字反向解码为字母映射出来&#xff0c;有多少种方法。 题目也说&…

基于java+SpringBoot+Vue的篮球竞赛预约平台设计与实现

基于javaSpringBootVue的篮球竞赛预约平台设计与实现 开发语言:Java数据库:MySQL技术:SpringBootMyBatis工具:IDEA/Ecilpse、Navicat、Maven 系统展示 前台展示 后台展示 系统简介 篮球竞赛预约平台以springboot作为框架&#xff0c;b/s模式以及MySql作为后台运行的数据库&a…

线程池的7大参数

线程池的7大参数 一、 corePoolSize 线程池核心线程大小 核心线程永远不会销毁&#xff0c;即使他们处于空闲状态&#xff0c;除非设置了allowCoreThreadTimeOut。任务提交到线程池后&#xff0c;首先会检查当前线程数是否达到了corePoolSize&#xff0c;如果没有达到的话&…