详解C语言函数:深入了解函数的使用和特性

目录

引言

一、函数的概念

1.1 函数关键特点

1.2 函数的组成部分

1.3 函数声明和定义格式

二、函数分类

2.1 库函数

使用库函数的步骤

2.2 自定义函数

创建自定义函数的步骤

三、函数的参数类型

3.1 形式参数(形参):

格式:

示例:

3.2 实际参数(实参):

格式:

示例:

四、函数调用

4.1 传值调用(Call by Value):

特点

示例

4.2 传址调用(Call by Reference):

特点:

示例

五、函数的嵌套调用和链式访问

5.1 函数的嵌套调用

示例

5.2 链式访问

示例

七、函数的声明和定义

7.1 函数的声明

格式

7.2 函数的定义 

格式

7.3 示例

八、分文件编写

8.1 分文件编写的步骤

8.2 示例

头文件 calculator.h

源文件 calculator.c

主文件 main.c

九、函数递归

9.1 递归的关键要素

9.2 递归的示例

9.3 递归的优缺点

9.4 递归的注意事项

十、栈溢出

10.1 原因

10.2 影响

10.3 预防栈溢出的方法

10.4 示例

结束语


引言

嗨,编程的冒险者们!今天,我将带你们进入函数的神奇世界,就像是探索了一个充满谜题和美味食物的迷宫🚀🍔。

我们可以把函数比作是编程的秘密配方,每个函数就像是一道独特的料理,拥有其独特的味道和风味。而这篇博客,就是为了揭示这些秘密配方的制作过程!从调味品到烹饪方式,让我们一起揭开C语言函数的神秘面纱,开始我们的编程烹饪之旅吧!🍳🧁🌮

一、函数的概念

当我们谈论编程中的函数时,就像是在探索一座魔幻厨房,每个角落都充满了独特的烹饪法和食材组合。那么,什么是函数呢?在这个神奇的编程世界中,函数就是你的独特食谱,用于完成特定的任务。

1.1 函数关键特点

  1. 模块化 函数将代码分割成小块,每个函数专注于完成一个特定的任务。这样,你可以更清晰地组织代码,提高可读性和可维护性。

  2. 复用性 一旦你创建了一个函数,你可以在程序的不同部分多次调用它,无需重复编写相同的代码。这大大提高了代码的复用性和效率。

  3. 抽象性 函数隐藏了内部实现细节,使你只需关注函数的输入和输出。这种抽象让你能够更专注于问题的解决,而不必过多关心实现细节。

  4. 可维护性 将功能模块化后,当你需要进行修改或优化时,只需关注特定函数而不影响其他部分,从而降低了出错的风险

1.2 函数的组成部分

  1. 函数名 用于唯一标识函数。好的函数名应该具有描述性,能够表达出函数的作用。

  2. 参数列表 一组在函数调用时传递给函数的值。参数是函数执行的“食材”。

  3. 返回类型 指定函数返回值的类型。函数可以有返回值,也可以没有。

  4. 函数体 包含实际的代码,执行特定的任务。这是函数的“烹饪步骤”

1.3 函数声明和定义格式

在使用函数之前,你需要声明函数以告诉编译器函数的存在和特性。函数的声明包括函数名、参数列表和返回类型。然后,在程序的其他地方,你需要定义函数,即提供函数体内的实际代码

// 函数声明
返回类型 函数名(参数列表);int main() {// 调用函数返回类型 result = 函数名(参数值);return 0;
}// 函数定义
返回类型 函数名(参数列表) {// 函数体// 执行任务的代码return 返回值;
}

让我们通过一个简单的示例来说明这些要素:

#include <stdio.h>// 函数声明
int add(int num1, int num2);int main() {int result = add(5, 7);printf("5 + 7 = %d\n", result);return 0;
}// 函数定义
int add(int num1, int num2) {int sum = num1 + num2;return sum;
}

二、函数分类

2.1 库函数

库函数是预先编写好的函数,由编程语言或操作系统提供,以供程序员在自己的代码中使用。这些函数涵盖了各种常见的任务,如数学运算字符串处理文件操作等,让你能够更快速地实现复杂的功能。

使用库函数的步骤

  1. 包含头文件 首先,你需要包含与你想要使用的库函数对应的头文件。这些头文件通常以.h为扩展名。

  2. 调用库函数 一旦你包含了头文件,就可以在你的代码中调用库函数了。使用函数的名称和参数列表,就可以完成特定的任务。

  3. 编译 最后,确保你的代码能够正确链接到库函数。这通常需要指定编译器链接相应的库。

让我们演示使用C标准库中的sqrt函数,这个函数用于计算一个数的平方根。

#include <stdio.h>  // 包含标准I/O库的头文件
#include <math.h>   // 包含数学库的头文件int main() {double number = 25.0;double squareRoot = sqrt(number);  // 调用sqrt函数计算平方根printf("The square root of %.2f is %.2f\n", number, squareRoot);return 0;
}

在这个示例中,我们包含了<math.h>头文件,这是C标准库中的数学库。然后,我们使用了sqrt函数来计算给定数字的平方根。通过这个简单的例子,你可以体会到库函数的威力,无需手动实现复杂的数学运算,而是利用现有的函数来解决问题。

库函数的使用让你的编程生活更加轻松和高效。无论是数学运算、字符串处理、内存管理还是文件操作,库函数都能够为你提供强大的功能。接下来,我们将继续探索自定义函数,这是展现你独特编程技能的机会,就像是创作了一道独一无二的美食!🍲🍰🍣

2.2 自定义函数

正如大厨独创的独特菜谱一样,自定义函数让你能够编写符合自己需求的独特代码块。通过自定义函数,你可以将一系列操作封装起来,创建属于自己的编程风格和模块。

创建自定义函数的步骤

  1. 定义函数 首先,你需要定义自己的函数,这包括函数名、参数列表、返回类型和函数体。函数名应该具有描述性,能够清楚地表达函数的作用。

  2. 函数体 在函数体中,你可以编写实际的代码,完成特定的任务。这些任务可以是数学运算、数据处理、逻辑判断等等。

  3. 调用函数 一旦你定义了函数,就可以在程序中的其他地方调用它。通过使用函数名和参数,你可以执行函数内的代码块。

下面是一个简单的自定义函数示例,我们将创建一个名为calculateSquare的函数,用于计算一个数的平方。

#include <stdio.h>// 函数声明
double calculateSquare(double num);int main() {double number = 5.0;double square = calculateSquare(number);  // 调用自定义函数printf("The square of %.2f is %.2f\n", number, square);return 0;
}// 函数定义
double calculateSquare(double num) {double square = num * num;return square;
}

在这个示例中,我们首先声明了名为calculateSquare的函数,它接受一个double类型的参数,并返回一个double类型的值。然后,在main函数中,我们调用了这个自定义函数,将计算结果存储在square变量中,并通过printf函数输出。

通过自定义函数,你可以将复杂的操作封装起来,提高代码的可读性和可维护性。这就像是创作了一道属于自己的独特美食,让编程更具创意和个性!🍝🍛🍱

三、函数的参数类型

当谈论函数参数时,通常会区分两个重要的概念:形式参数和实际参数。形式参数是函数定义中用来表示参数的变量,而实际参数是在函数调用时传递给函数的具体值。让我们来详细了解这两个概念以及它们的作用。

3.1 形式参数(形参):

形式参数是在函数定义中声明的参数,它们充当函数体内部的局部变量。形参在函数定义中给出的类型和名称,决定了函数将接受哪种类型的参数。

格式:

返回类型 函数名(参数类型 形式参数名) {// 函数体
}

示例:

#include <stdio.h>void printMessage(char msg[]) {printf("%s\n", msg);
}int main() {char message[] = "Hello, world!";printMessage(message);return 0;
}

在这个示例中,printMessage 函数定义中的 char msg[] 就是形式参数。它在函数内部被当作局部变量使用,用于存储传递给函数的字符串。

3.2 实际参数(实参):

实际参数是在函数调用时传递给函数的具体值,它们是实际参与函数运算的数据。实参可以是常量、变量、表达式等,这些值被传递给函数,供函数在执行时使用。

格式:

函数名(实际参数);

示例:

#include <stdio.h>int add(int num1, int num2) {return num1 + num2;
}int main() {int result = add(5, 7);printf("5 + 7 = %d\n", result);return 0;
}

在这个示例中,add 函数的调用中的 57 就是实际参数。这些实参的值被传递给 add 函数,用于执行加法运算。

通过形式参数和实际参数,你可以将数据传递给函数并进行操作。形参定义了函数将接受哪种类型的参数,而实参提供了具体的值,使函数能够进行计算和处理。

四、函数调用

当我们在调用函数时,参数可以通过不同的方式传递给函数,这导致了两种主要的调用方式:传值调用和传址调用。让我们详细介绍这两种调用方式及其区别。

4.1 传值调用(Call by Value):

在传值调用中,函数接受的是实际参数的一个副本,而不是实际参数本身。这意味着函数内部对参数的任何修改都不会影响原始的实际参数值。

特点

  • 函数的形式参数(形参)充当局部变量,对形参的修改不会影响外部实际参数(实参)。
  • 适用于那些不需要修改实参值的情况。

示例

#include <stdio.h>void modifyValue(int num) {num = num * 2;printf("Inside function: %d\n", num);
}int main() {int value = 5;modifyValue(value);printf("Outside function: %d\n", value);return 0;
}

在传值调用中,函数内部对参数 num 的修改不会影响到 value 变量的值。

4.2 传址调用(Call by Reference):

在传址调用中,函数接受的是实际参数的地址(指针),从而可以直接访问和修改实际参数的值。这意味着函数内部的修改会影响原始的实际参数值。

特点:

  • 函数的形参是指向实际参数内存地址的指针。对形参的修改会直接影响实际参数。
  • 适用于需要修改实参值的情况。

示例

#include <stdio.h>void modifyValue(int *ptr) {*ptr = *ptr * 2;printf("Inside function: %d\n", *ptr);
}int main() {int value = 5;modifyValue(&value);printf("Outside function: %d\n", value);return 0;
}

在传址调用中,函数内部对参数 ptr 所指向的值的修改会直接影响到 value 变量的值。

在C语言中,默认情况下是使用传值调用。如果你想要使用传址调用,需要将实际参数的地址传递给函数。这两种调用方式各有优劣,视具体情况而定。

传值调用适用于不需要修改原始值的情况,而传址调用适用于需要函数内部修改实参值的情况。

五、函数的嵌套调用和链式访问

函数的嵌套调用是一种强大的编程技巧,它允许你在一个函数内部调用另一个函数。这样的嵌套调用可以实现更复杂的操作,将大的问题分解成小的问题,并逐步解决。而链式访问是在函数调用的基础上,将多个函数调用连接起来,形成一个连续的操作序列。

5.1 函数的嵌套调用

函数的嵌套调用让你能够在一个函数内部调用另一个函数。这种技巧可以帮助你组织代码,使之更清晰和模块化。当一个函数的执行需要依赖于另一个函数的结果时,嵌套调用可以提供非常便捷的方式。

示例

#include <stdio.h>int multiply(int a, int b) {return a * b;
}int add(int x, int y) {return x + y;
}int main() {int num1 = 3, num2 = 4, num3 = 2;int result = add(multiply(num1, num2), num3);printf("Result: %d\n", result);return 0;
}

在这个示例中,multiply 函数用于计算两个数的乘积,add 函数用于计算两个数的和。在 main 函数中,我们将 multiply(num1, num2) 的结果作为第一个参数传递给 add 函数,然后再将 num3 作为第二个参数传递。这样的嵌套调用可以在一行代码中完成多个函数的调用,使代码更紧凑。

5.2 链式访问

链式访问是指将多个函数调用连接起来,每个函数调用都作用于前一个函数调用的结果。这种技巧在某些情况下可以使代码更具可读性,特别是在进行一系列相关的操作时。

示例

#include <stdio.h>int add(int x, int y) {return x + y;
}int multiply(int a, int b) {return a * b;
}int main() {int num1 = 3, num2 = 4, num3 = 2;int result = add(num1, num2);          // 计算和result = multiply(result, num3);       // 计算乘积printf("Result: %d\n", result);return 0;
}

在这个示例中,我们首先调用 add 函数计算 num1num2 的和,然后将结果传递给 multiply 函数,计算乘积。通过这种链式访问,可以更清楚地看到一系列操作的流程。

七、函数的声明和定义

在编写较大的程序时,函数的声明和定义变得非常重要

函数的声明告诉编译器函数的存在和特征,从而在调用函数之前提前知道函数的信息。函数的定义提供了实际的函数实现,包括函数体内的代码。

7.1 函数的声明

函数的声明告诉编译器有一个函数存在,以及该函数的名称、参数列表和返回类型。通过声明函数,你可以在函数调用之前让编译器知道函数的特征。

格式

返回类型 函数名(参数列表);

7.2 函数的定义 

函数的定义提供了函数的实际实现,包括函数体内的代码。函数的定义通常在函数的声明之后,定义了函数在被调用时具体执行的任务。

格式

 

7.3 示例

 

在这个示例中,我们首先在 main 函数前面声明了 add 函数,这使得编译器知道了 add 函数的存在、参数和返回类型。然后在 main 函数中调用了 add 函数。

八、分文件编写

随着程序逐渐增大,将所有代码都写在一个文件中会变得不太实际和难以维护。为了提高代码的组织性和可维护性,可以将代码分割成多个文件,每个文件负责不同的功能。这就是分文件编写的概念。

8.1 分文件编写的步骤

  1. 头文件(Header Files) 头文件包含了函数的声明、结构体的定义、宏等。头文件通常具有 .h 扩展名,它们提供了对函数和结构体的接口。

  2. 源文件(Source Files) 源文件包含了函数的实际定义和具体代码。源文件通常具有 .c 扩展名,它们实现了头文件中声明的函数。

  3. 编译链接 在编译过程中,编译器需要将头文件和源文件一起处理,以生成最终的可执行文件。链接器将各个源文件中的代码合并在一起,生成最终的程序。

8.2 示例

头文件 calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_Hint add(int num1, int num2);
int subtract(int num1, int num2);#endif

源文件 calculator.c

#include "calculator.h"int add(int num1, int num2) {return num1 + num2;
}int subtract(int num1, int num2) {return num1 - num2;
}

主文件 main.c

#include <stdio.h>
#include "calculator.h"int main() {int num1 = 10, num2 = 5;int sum = add(num1, num2);int difference = subtract(num1, num2);printf("Sum: %d\n", sum);printf("Difference: %d\n", difference);return 0;
}

在这个示例中,我们将代码分为三个文件。calculator.h 是头文件,包含了 addsubtract 函数的声明。calculator.c 是源文件,实现了这两个函数。main.c 是主文件,包含了主函数和函数调用。在编译和链接时,编译器会将这三个文件一起处理,生成最终的可执行文件。

分文件编写让代码更具模块化,使得每个文件负责特定的功能。这种方法不仅提高了代码的可读性和可维护性,还有助于团队协作,每个成员可以专注于不同的模块。在分文件编写中,正确的头文件引用和函数声明是非常重要的,它们确保了代码的正确连接和执行。

九、函数递归

递归是一种编程技巧,它允许一个函数在其内部调用自身。递归是通过将大问题分解为更小的、相似的子问题来解决问题的方法。递归函数在解决问题时,将问题分解为一个或多个较小的问题,然后逐步解决这些小问题,最终得到问题的解。

9.1 递归的关键要素

  1. 基本情况(Base Case) 每个递归函数都需要定义一个基本情况,即无需再继续递归的情况。基本情况通常是递归问题的最小规模,可以直接求解。

  2. 递归调用(Recursive Call) 在递归函数内部,它会调用自身来解决更小规模的问题。递归调用通常通过改变函数的参数来逐步减小问题的规模,直到达到基本情况。

9.2 递归的示例

一个经典的递归示例是计算阶乘,即一个正整数 n 的阶乘表示为 n!,其计算方式为 n! = n * (n - 1) * (n - 2) * ... * 1

#include <stdio.h>int factorial(int n) {// 基本情况:0! 和 1! 都等于 1if (n == 0 || n == 1) {return 1;}// 递归调用:n! = n * (n - 1)!return n * factorial(n - 1);
}int main() {int n = 5;int result = factorial(n);printf("%d! = %d\n", n, result);return 0;
}

在这个示例中,factorial 函数通过递归的方式计算阶乘。基本情况是 0!1! 都等于 1,递归调用使用 n * factorial(n - 1) 的方式逐步计算 n!

9.3 递归的优缺点

优点:

  • 可以解决一些复杂问题,将问题分解为更小的子问题。
  • 代码结构清晰,更易于理解和维护。

缺点:

  • 需要额外的函数调用开销,可能导致性能问题。
  • 如果递归不受控制,可能会导致堆栈溢出。9.

9.4 递归的注意事项

  • 确保每次递归都向基本情况靠近,否则可能陷入无限递归。
  • 考虑性能问题,一些问题可以通过迭代方式更有效地解决。
  • 使用递归时,确保提供合适的终止条件。

十、栈溢出

栈溢出是在编程中常见的错误,它发生在函数调用和递归过程中,当程序的调用栈空间不足以容纳更多的函数调用和局部变量时,就会发生栈溢出。

10.1 原因

栈是一种存储函数调用、局部变量和临时数据的内存区域。当一个函数被调用时,其局部变量和返回地址等信息会被压入栈中,函数执行完毕后这些信息会从栈中弹出。如果函数调用层级太深或函数内部使用了大量的局部变量,栈空间可能会耗尽,导致栈溢出。

10.2 影响

栈溢出可能导致程序崩溃、异常终止或不可预测的行为。常见的影响包括:

  • 程序崩溃并显示错误消息。
  • 导致无限循环或不正确的计算结果。
  • 可能覆盖其他内存区域,影响其他变量和数据。

10.3 预防栈溢出的方法

  1. 递归深度控制 在使用递归时,确保递归深度不会太深,适时结束递归。
  2. 避免过多局部变量 减少函数内部的局部变量数量,或使用动态分配内存(堆)来存储大型数据。
  3. 迭代代替递归 对于可以使用迭代解决的问题,尽量使用迭代,避免无限递归。
  4. 增加栈大小 有些编程环境允许调整栈的大小,但不是所有情况都适用。
  5. 使用尾递归优化 一些编程语言支持尾递归优化,使递归调用不会增加额外的栈空间。

10.4 示例

#include <stdio.h>void recursiveFunction(int count) {printf("Count: %d\n", count);recursiveFunction(count + 1); // 递归调用
}int main() {recursiveFunction(1);return 0;
}

在这个示例中,recursiveFunction 函数会不断递归调用自身,每次增加计数。如果递归深度过大,栈可能会溢出。预防栈溢出的方法之一是通过添加终止条件来控制递归的次数

栈溢出是需要警惕的问题,特别是在涉及递归和大量函数调用的情况下。通过合理设计程序逻辑,限制递归深度,避免过多局部变量,以及使用适当的数据结构,你可以降低栈溢出的风险,使你的程序更稳定和可靠。

结束语

在本篇博客中,我们跟随着函数的编程旅程,就像是探险家在代码的大陆上寻宝一样!我们穿越了函数的迷宫,深入了解了它的每一个角落,从基础概念一直到递归的神秘境界。

🚀 函数,就像是编程的魔法咒语,让代码得以模块化,让复杂问题变得迎刃而解。我们一起领略了函数的魅力,从库函数到自定义函数,从函数的传参到递归的优雅,每一步都让我们更加强大!

🔍 无论是在代码的森林中追寻Bug,还是在问题的海洋里航行创新,函数都是你的忠实向导。通过深入理解函数的机制,我们更能在编程的世界中驾驭风云、创造奇迹!

📚 编程世界如此丰富多彩,而函数则是其中的一抹明亮的色彩。通过不断学习、实践和探索,你将在代码的世界中书写属于自己的传奇!

感谢你的耐心阅读,希望本篇博客能够为你打开函数的奥秘之门。如果你有任何问题、想法,或是想要继续探讨关于编程的话题,欢迎随时与我交流。愿你在编程的旅程中充满乐趣,继续探索,继续创造!

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

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

相关文章

springboot工程集成前端编译包,用于uni-app webView工程,解决其需独立部署带来的麻烦,场景如页面->画布->图片->pdf

前端工程 访问方式 http://127.0.0.1:8080/context/frontEnd/index放行 public class SecurityConfig extends WebSecurityConfigurerAdapter { "/frontEnd/**",SysFrontEndController import lombok.extern.slf4j.Slf4j; import nl.basjes.shaded.org.springfram…

【Mybatis】调试查看执行的 SQL 语句

1. 问题场景&#xff1a; 记录日常开发过程中 Mybatis 调试 SQL 语句&#xff0c;想要查看Mybatis 中执行的 SQL语句&#xff0c;导致定位问题困难 2. 解决方式 双击shift找到mybatis源码中的 MappedStatement的getBoundSql()方法 public BoundSql getBoundSql(Object para…

leetcode - 75. 颜色分类(java)

颜色分类 leetcode - 75. 颜色分类题目描述双指针代码演示 双指针算法专题 leetcode - 75. 颜色分类 难度 - 中等 原题链接 - 颜色分类 题目描述 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地对它们进行排序&#xff0c;使得相同颜色的元素相邻&…

栈和队列详解(1)

目录 一、什么是栈&#xff1f; 二、创建一个我们自己的栈 1.前置准备 1.1需要的三个文件 1.2结构体的创建和头文件的引用 2.接口的实现 2.1初始化栈结构体 2.2尾插(压栈) 2.3栈存放的元素个数和判断栈是否为空 2.4获取栈顶元素 2.5出栈 2.6摧毁栈 2.7测试接口 三、…

Java基础入门篇——IDEA开发第一个入门程序(五)

目录 一、IDEA层级结构分类 二、IDEA层级结构介绍 三、IDEA层级关系 四、创建IDEA中的第一个代码 一、IDEA层级结构分类 IntelliJ IDEA的项目结构主要分为以下几个层级&#xff1a; Project&#xff1a; 项目Module: 模块Package: 包Class&#xff1a; 类 一个项目里面…

预测赢家(力扣)dfs + 备忘录 JAVA

给你一个整数数组 nums 。玩家 1 和玩家 2 基于这个数组设计了一个游戏。 玩家 1 和玩家 2 轮流进行自己的回合&#xff0c;玩家 1 先手。开始时&#xff0c;两个玩家的初始分值都是 0 。每一回合&#xff0c;玩家从数组的任意一端取一个数字&#xff08;即&#xff0c;nums[0]…

【LeetCode】45. 跳跃游戏 II - 贪婪算法

目录标题 2023-8-11 09:49:25 45. 跳跃游戏 II 2023-8-11 09:49:25 自己没做出来&#xff0c;废物Orz class Solution {public int jump(int[] nums) {int length nums.length;int end 0;int maxPosition 0;int steps 0;for (int i 0; i < length - 1; i) {maxPosit…

首批获得金融级行业云平台认证,天翼云深耕行业云

云计算下半场看什么&#xff1f; 无疑是金融、政务、制造等传统政企用户的上云与用云。随着数字经济发展和产业数字化的提速&#xff0c;上云已是政企用户推动其数字化转型不断深入的重要抓手&#xff0c;成为不可阻挡的趋势。 与互联网用户相比&#xff0c;政企用户上云极为…

从数据仓库到数据结构:数据架构的演变之路

在上个世纪&#xff0c;从电子商务巨头到医疗服务机构和政府部门&#xff0c;数据已成为每家组织的生命线。有效地收集和管理这些数据可以为组织提供宝贵的洞察力&#xff0c;以帮助决策&#xff0c;然而这是一项艰巨的任务。 尽管数据很重要&#xff0c;但CIOinsight声称&…

那些年的Java开发经验记录

Java同步锁(浅显易懂&#xff0c;精简讲解) 详细讲解可以看这篇文章Java对象锁和类锁全面解析&#xff08;多线程synchronized关键字&#xff09; 精简如下&#xff1a; 1.不管什么锁&#xff0c;都是属于对象锁(类也是一种对象) 2.一个对象只有一个锁 3.锁最大可以锁整个…

【框架类】—Vue3的生命周期

一、生命周期的相关函数 onBeforeMount 页面渲染之前 和 onMounted渲染之后 示例 <template><div class"test"><div ref"el">组件初始化</div></div> </template> <script> //按需引入所需方法 import { ref,…

Redux - Redux在React函数式组件中的基本使用

文章目录 一&#xff0c;简介二&#xff0c;安装三&#xff0c;三大核心概念Store、Action、Reducer3.1 Store3.2 Reducer3.3 Action 四&#xff0c;开始函数式组件中使用4.1&#xff0c;引入store4.1&#xff0c;store.getState()方法4.3&#xff0c;store.dispatch()方法4.4&…

04-4_Qt 5.9 C++开发指南_时间日期与定时器

文章目录 1. 时间日期相关的类2. 源码2.1 可视化UI设计2.2 dialog.h2.3 dialog.cpp 1. 时间日期相关的类 时间日期是经常遇到的数据类型&#xff0c;Qt 中时间日期类型的类如下。 QTime:时间数据类型&#xff0c;仅表示时间&#xff0c;如 15:23:13。 QDate:日期数据类型&…

虹科方案 | 汽车总线协议转换解决方案

汽车总线&#xff1a; 汽车总线是一种用于在车辆电子系统中传输数据和控制信息的通信系统。它允许不同的电子控制单元&#xff08;ECU&#xff09;在车辆中相互通信&#xff0c;协调各个系统的操作&#xff0c;以实现功能的集成和协同工作。 在现代汽车中&#xff0c;综合通信…

微信公众号模板消息推送测试Python版无需服务器-保姆级教程

手上有个项目&#xff0c;是服务器挂着自动化的爬虫的&#xff0c;但我用的那个IP代理商没有用尽报警&#xff0c;导致几次IP用尽&#xff0c;程序爬不到数据&#xff0c;进程死循环了。之前想过发邮箱提醒我&#xff0c;但是邮箱把又不及时&#xff0c;老忘记看&#xff0c;因…

C语言必会题目(1)

W...Y的主页 &#x1f60a; 代码仓库分享❤️ 在学习语言时&#xff0c;最重要的就是练习&#xff0c;光听不练假把式。下面我就推荐一些C语言必会的题。 执行下面程序&#xff0c;正确的输出是&#xff08; &#xff09; int x5,y7; void swap() { int z; zx; xy; yz; } int…

数字孪生三剑客来了!MapGIS Earth for Unreal的自述

嗨&#xff0c;大家好&#xff01;我的名字叫MapGIS Earth for Unreal&#xff0c;是MapGIS数字孪生平台产品家族的一员。提起我&#xff0c;大家可能不熟悉&#xff0c;但是提起数字孪生&#xff0c;想必大家倍感兴趣。 数字孪生是充分利用物理模型、传感器更新、运行历史等数…

【git】解决遇到的问题

目录 一、error: RPC failed; curl 6 OpenSSL SSL_read: Connection was reset, errno 10054 二、error: RPC failed; curl 6 OpenSSL SSL_read: Connection was reset, errno 10054 一、error: RPC failed; curl 6 OpenSSL SSL_read: Connection was reset, errno 10054 报…

2023最新Windows编译ffmpeg详细教程,附msys2详细安装配置教程

安装MSYS2 msys2是一款跨平台编译套件&#xff0c;它模拟linux编译环境&#xff0c;支持整合mingw32和mingw64&#xff0c;能很方便的在windows上对一些开源的linux工程进行编译运行。 类似的跨平台编译套件有&#xff1a;msys&#xff0c;cygwin&#xff0c;mingw 优势&…