关于我个人的编码规范(C/C++)

文章目录

  • 前言
  • 一、文件结构
    • 1. 版权和版本声明(不是必须,但是我建议看看)
    • 2. 头文件结构
    • 3. 源文件结构
  • 二、排版(以 K&R 风格为主)
    • 1. 缩进与左花括号的位置
    • 2. 空行的插入
    • 3. 该分行就分行
    • 4. 花括号
    • 5. 长语句分段
    • 6. 空格
    • 7. 无用的代码必须删除
  • 三、注释
    • 1. 注释用什么语言?
    • 2. 注释缩进
    • 3. 程序块结束注释
    • 4. 两种注释的用法
    • 5. `switch` 语句如无需 `break`,须加上明确的注释
    • 6. 函数块的注释
  • 四、命名规则
    • 1. 变量与函数的命名
    • 2. 宏定义和常数的命名
  • 五、其他
    • 1. 结构体定义注意字节对齐
    • 2. 定义变量时同时进行初始化
    • 3. 禁止浮点数直接进行等于或者不等于的比较操作
    • 4. 超过两级的运算符表达式必须使用括号分离
    • 5. 函数参数不能出现结构体
    • 6. 有参宏定义表达式都必须使用括号
    • 7. 使用有参宏定义,禁止参数带自增自减运算符

前言

在当今这个代码如诗的时代,每一行字符都不再仅仅是逻辑与指令的堆砌,它们是思想的载体,是创新的脉络,是协作的桥梁。编程,这一门独特的语言艺术,不仅要求我们精准地传达机器可执行的指令,更期望我们在编织这些数字世界基石的同时,展现出一种对美的追求和对同行的尊重。正因如此,编码风格规范的重要性日益凸显,它不仅是技术严谨性的体现,更是团队协作效率与代码可维护性的重要保障。

我之所以提笔撰写这篇关于编码风格规范的文章,是源自于一个日益显著的观察:在这个信息爆炸、开源共享成为常态的互联网环境中,代码的多样性和随意性似乎成了一把双刃剑。一方面,它激发了无限的创造力;另一方面,却也导致了编码风格的参差不齐。从网络的广阔舞台到日常工作的点滴,不规范的编码风格如同迷雾,遮蔽了代码的清晰度,增加了理解与维护的难度,甚至在无形中设置了沟通的障碍。

身边同事的代码,网上的开源项目,无一不在提醒我们,编码风格规范不仅仅是一套规则那么简单,它是编程文化的体现,是工程师素养的标志。缺乏统一和规范的编码习惯,就如同一座城市缺少规划,虽充满活力却杂乱无章,让每一个试图在其间穿行的人感到困惑与挑战。

希望通过这篇文章,能够唤醒每一位程序员对编码之美、对团队合作精神的深刻认识,让我们共同努力,将代码编织成既功能强大又赏心悦目的艺术品,为数字世界的建设添砖加瓦。让我们一起踏上这段旅程,探索编码风格规范的奥秘,共创更加高效、优雅的编程未来。

代码风格是因人而异的, 而且我不愿意把自己的观点强加给任何人,但这就像我去做任何事情都必须遵循的原则,我也希望在绝大多数事上保持这种的态度。所以综合参考了相关文献,在我工作时要求的编码规范基础上,写了这篇关于 C/C++ 语言编程风格的规则,希望对大家有所帮助。

本文参考了《Linux 内核代码风格》和我在某国产手机工作时的《Android 系统编码规范(C/C++)》

一、文件结构

1. 版权和版本声明(不是必须,但是我建议看看)

版权和版本的声明位于头文件和源文件的开头,其中包括版权、文件名称、功能描述、版本、创建日期、作者、修改记录。版权和版本的声明位于头文件和源文件的开头,内容有:

  1. 版权信息;
  2. 文件名称;
  3. 功能简短描述;
  4. 版本号;
  5. 创建日期;
  6. 作者;
  7. 修改记录。

具体内容如下,格式不局限于此,但上述信息必须包含在内:

/********************************************************************* Copyright (c) 201X- 201X XXXXXXXXX, Ltd.* File: example.c* Description: This file contains the implementation of a simple example program.* Version: 1.0* Date: 2023-3-31* Author: zhengxinyu13@qq.com* ---------- Revision History ----------* <version> <date> <author> <desc>* Revision 2.0, 2024-5-13, zhengxinyu13@qq.com*   Modified to be suitable to the new coding rules in all functions.* Revision 1.5, 2023-7-24, zhengxinyu13@qq.com*   Some features have been updated.********************************************************************/

其中版权、文件名称、功能描述、版本、创建日期、作者这六项是竖向排列,修改记录中的版本号、修改日期、作者、修复说明是横向排列,且修改记录为倒叙(类似 git log 的记录)。

不过对于我个人已经发布到网上的代码而言,我通常会删掉版权一栏,已经是开源的代码了,就没有版权一说了,所以我个人使用的声明如下:

/********************************************************************* File: * Description: * Version: * Date: * Author: zhengxinyu13@qq.com* ---------- Revision History ----------* <version> <date> <author> <desc>* ********************************************************************/

[!NOTE]

这里特殊说明一下,一般作者一栏都是写自己的个人邮箱,在软件开发领域,邮箱已经成为了一种标准的联系方式。它简单易用,几乎所有人都有邮箱,并且可以在全球范围内使用。相比电话等联系方式,邮箱提供了一种可以用于联系但又相对匿名的方式(毕竟谁也不希望电话号码被泄露,特别是中国人,电话卡绑定了太多东西了)。而且大部分代码托管平台的通知系统是基于电子邮件的。通过使用邮箱,开发者可以及时接收到有关项目的更新、问题、合并请求等重要信息。

2. 头文件结构

头文件除了版权和版本声明,还必须依次包含预处理块、函数和结构声明。头文件有三部分内容组成:

  1. [头文件开头处的版权和版本声明](#1. 版权和版本声明(不是必须,但是我建议看看));
  2. 预处理块,为了防止头文件被重复引用,应当使用 #ifndef / #define / #endif 结构产生预处理块;
  3. 函数和结构声明等,头文件中只存放 “声明” 而不存放 “定义”,以便于其他文件引用时不会出现重定义错误,inline 内联函数除外。

下面给出一个头文件的实例(假设这个文件叫 Bitmap.h):

#ifndef __BITMAP_H__
#define __BITMAP_H__#include <SkBitmap.h>
#include "..."namespace android {class Bitmap {public:Bitmap(JNIEnv* env, jbyteArray storageObj, void* address,const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);size_t rowBytes() const;...};
} // namespace android#endif //__BITMAP_H__

这里要特别强调头文件中的 #include "..." ,我们只在自己的头文件中包含必须的其他头文件,属于源文件需要的头文件在源文件中包含。

[!NOTE]

使用 #ifndef / #define / #endif 结构时,命名宏除了字母全部大写之外,在宏前后都会多打两个下划线,这属于是行业编码风格约定俗成的规矩了,没有什么特殊意义。

3. 源文件结构

源文件除了版权和版本声明,还必须依次包含头文件的引用和程序的实现体。源文件有三部分内容组成:

  1. [头文件开头处的版权和版本声明](#1. 版权和版本声明(不是必须,但是我建议看看));
  2. 头文件引用;
  3. 程序的实现体(包括数据和代码)。

下面给出一个源文件的实例(假设这个文件叫 Bitmap.cpp):

#include <...>
#include "..."
...
#include “Bitmap.h”
...
namespace android {size_t rowBytes() const {return mRowBytes;}...
} // namespace android

二、排版(以 K&R 风格为主)

1. 缩进与左花括号的位置

缩进的全部意义就在于清楚的定义一个控制块起止于何处,网上很多代码的缩进风格让人看的真的是很难受,建议统一设 Tab 为 4 个空格,采用 Tab 缩进。并且设置按下 Tab 后,自动把 Tab 转换为 4个空格(老程序员都懂)。

至于左花括号的位置,不同人有不同的看法,而我已经习惯了工作中的规范要求,所以我写程序块时,左花括号与它的语句同行,用空格隔开,右花括号与引用它们的语句左对齐,花括号之内的代码块在缩进位置处左对齐。而写函数时,左花括号则另起一行,与引用语句左对齐,其余跟程序块一样。具体如下:

void example_fun_1(void)
{
... // program code
}void example_fun_2(void)
{for (...) {... // program code}if (...) {... // program code} else {... // program code}switch (variable) {case value1:... // program codebreak;case value1:... // program codebreak;default:... // program codebreak;}
}

关于左花括号的位置,也是一个涉及个人风格的问题,我选用这个写法,沿用了 Kernighan 和 Ritchie(C 语言之父,两人一起编写了[《The C Programming Language》](https://baike.baidu.com/item/C程序设计语言/10640335?fromtitle=The C Programming Language&fromid=1838395))的编码风格,也就是所谓的 K&R 风格,不过我也没有全部照搬,例如函数就不是这个风格,只要用于区分程序块和函数。

2. 空行的插入

相对独立的程序块之间、变量说明之后必须加空行,空行起着分隔程序段落的作用,将使程序的布局更加清晰。

int ret = -1;if (NULL == dst || NULL == proc) {perror();return false;
}const jint *array = env->GetIntArrayElements(srcColors, NULL);
const SkColor *src = (const SkColor *)array + srcOffset;

3. 该分行就分行

切勿把多个短语句写在一行,一行代码只做一件事情,这样的代码容易阅读,并且便于写注释。

以下是不规范的写法:

rect.height = 0; rect.width = 0;if (NULL == dst || NULL == proc) return;

以下是规范的写法:

rect.height = 0;
rect.width = 0;if (NULL == dst || NULL == proc)return;

4. 花括号

这里又聊到了花括号,一般认为 iffordo-whilewhileswitch 等语句必须使用花括号括起来,从上面的示例也可以看出。

当然,也不是任何情况都要加上这个花括号,当只有一个单独的语句的时候,不用加不必要的大括号。如下:

if (condition)action();

或者这样:

if (condition)do_this();
elsedo_that();

不过,这并不适用于只有一个条件分支是单语句的情况,这时所有分支都要使用大括号:

if (condition) {do_this();do_that();
} else {otherwise();
}

这里只介绍了 if-else 语句,同样适用于 fordo-whilewhile 等语句。

5. 长语句分段

较长的语句必须分成多行书写,这里说的较长的语句,其实没有统一标准,我个人的标准是每行不超过 80 个字符(包括每次缩进的空格在内)。长表达式要在低优先级操作符处划分新行,操作符放在新行之首(以便突出操作符)。划分出的新行要进行适当的缩进,使排版整齐,语句可读。

例如:

// 判断语句有较长表达式时
if ((very_longer_variable1 >= (very_longer_varable2))&& (very_longer_varable3) <= (very_longer_varable4)&& (very_longer_varable5) <= (very_longer_varable6)) {dosomething();
}// 函数参数较多或较长时
static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,jintArray pixelArray, jint offset, jint stride,jint x, jint y, jint width, jint height)
{... // program code
}// 循环语句有较长表达式时
for (very_longer_initialization;very_longer_condition;very_longer_update) {dosomething();
}

6. 空格

比较运算符、赋值运算符、算术运算符、逻辑运算符、位域运算符等双目运算符的前后必须加空格,采用这种松散方式编写代码的目的是使代码更加清晰。以下是各个示例:

  1. 逗号,分号只在后面加空格

    dosomething(parm1, parm2, parm3);for (i = 0; i < MAX_LENGTH; i++) {... // program code
    }
    
  2. 双目操作符的前后加空格

    比较操作符,赋值操作符( =+=),算术操作符( +% 等),逻辑操作符( &&& 等),位域操作符( << 等)等双目操作符的前后加空格。

    if (current_time >= MAX_TIME_VALUE)... // program codevar1 = var2 + var3;
    var1 *= 2;
    var1 = var2 ^ 2;
    
  3. 结构体内部变量不加空格

    p->id = pid; // "->"前后不加空格
    str.id = pid; // "."前后不加空格
    
  4. 单目操作符前后不加空格

    *p = 'a'; 		 // 内容操作"*"与内容之间
    flag = !isEmpty; // 非操作"!"与内容之间
    p = &mem;		// 地址操作"&" 与内容之间
    i++; 		    // "++","--"与内容之间
    
  5. 部分关键字语句与括号间加空格

    ifforwhileswitch 等与后面的括号间应加空格,使 if 等关键字更为突出、明显。

    if (var1 >= var2 && var3 > var4)
    

7. 无用的代码必须删除

代码文件不用的代码不要用注释等方法来保留在文件中,除非你注释掉的代码非常有代表意义(比如对 Android 源码的修改;有的代码使用特殊,别人来修改你的代码可能犯你当初的错误,那么你这部分注释掉的错误代码可以保留,并增加说明),否则不再使用的代码必须删除。

三、注释

1. 注释用什么语言?

关于注释该用中文还是英文要具体看你这个代码的目的是什么。如果是开源到 GitHub 上的项目,建议用英文,如果是开源到 Gitee 上的项目,那么中英文都行。如果只是学习阶段,用中文也没什么,毕竟中国国民英文水平摆在那里,大家有目共睹,不能强迫一个英语本来就不好的程序员强行使用英文写注释(要是公司要求就没办法了)。如果用中文写注释,要注意编码格式的问题,建议使用 UTF-8 的输入格式。

注释的内容必须清楚准确,拒绝二义性!

2. 注释缩进

注释与所描述内容必须进行同样的缩排,这可使程序排版整齐,并方便注释的阅读与理解。如下:

void example_fun( void ) {/* code one comments */CodeBlock One/* code two comments */CodeBlock Two
}

3. 程序块结束注释

超出一屏的程序块的结束行和分支语句(条件分支、循环语句等)结束行右方必须加注释标记,以表明某程序块的结束。主要是当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。如下:

if (...) {... // program codewhile (index < MAX_INDEX) {... // program code} // end of while (index < MAX_INDEX)
} // end of if (...)#ifdef __IDMAP_H__
...// program code
#else
...// program code
#endif // __IDMAP_H__

4. 两种注释的用法

早期 C 语言只有 /* */ 这种注释方式,最早使用 // 注释代码的是 Java,后来 C 语言也引入了 // 作为注释,其实两种注释产生的结构并没有什么区别。/* */ 更多用于多行的注释信息,例如前面提到的版权和版本信息等,就是用这种方法注释的。而 // 一般是单行代码进行注释。所以一般都是用 /* */ 注释程序块或者函数,注释必须位于其上方相近位置,放于上方则需与
其上面的代码用空行隔开。而 // 一般是写在单行代码的后面,只对一行代码作注释,如果注释内容过程,一行显示不下,也会考虑换成 /* */

5. switch 语句如无需 break,须加上明确的注释

switch 的每个 case 语句,默认要求有 break 返回;如果无需 break,必须加上明确的注释,这样比较清楚程序编写者的意图,有效防止无故遗漏 break 语句。

case CMD_UP:ProcessUp();break;
case CMD_DOWN:ProcessDown();break;
case CMD_FWD:ProcessFwd();if (...) {...break;} else {ProcessCFW_B(); // now jump into case CMD_A}
case CMD_A:ProcessA();break;
...
default:break;

6. 函数块的注释

在多数编程语言中,函数注释风格可能有所不同,但核心元素相似,通常包括函数的概述、参数说明、返回值说明、示例用法和注意事项等。例如,在 Java 或 C++ 中,可能会使用 Javadoc 或 Doxygen 风格的注释,其格式略有不同,但目的相同:

/*** @brief exampleFunction - A brief description of the function.* @param param1 (Type) Description of param1.* @param param2 (Type) Description of param2.* @return ReturnType Description of the return value.* @throws ExceptionType If something goes wrong, this exception is thrown.*/
ReturnType ReturnType exampleFunction(Type param1, Type param2) {// Function implementation...
}

下面是各个部分的含义:

  • @brief: 简要描述函数的作用或功能。
  • @param: 参数说明,描述函数接受的参数及其含义。
  • @return: 返回值说明,描述函数返回的内容或类型。
  • @throws: 异常说明,描述函数可能抛出的异常或错误情况。

这种文档注释通常用于提供函数的详细信息,使得其他开发者能够快速了解函数的使用方法和预期行为。

四、命名规则

1. 变量与函数的命名

我对于变量名和函数名的命名法,通常根据开发的情况来决定的。一般做 C51 单片机和 Linux 驱动相关的开发,用下划线命名法。开发 STM32 单片机、Arduino 单片机和 Linux 应用层程序时,用小驼峰命名法,少部分 Linux 应用层开发用大驼峰命名法。如果涉及到 FreeRTOS 相关的开发,可能还会用到匈牙利命名法

命名法只是基本要求,比较重要的是,千万不要用拼音去命名,除非是一些人名或者地名(人名或者地名一般也不太会出现在代码中),英文差没关系,可以去查,现在工具非常多。

也可以使用一些程序员公认的英文缩写,目前约定俗成的有如下表所示的英语单词:

常见单词惯用写法含义
argumentarg传入的参数
bufferbuf缓冲存储区
clockclk时钟
commandcmd命令
comparecmp比较
configurationcfg / conf / config配置
devicedev设备
errorerr错误
hexadecimalhex十六进制数的
incrementinc增量器
initalizeinit初始化
maximummax最大的
messagemsg消息
minimummin最小的
parameterpara参数
previousprev上一个的
registerreg注册
semaphoresem信号标志
statisticstat统计数据
synchronizesync同步器
temptmp临时变量
functionfun函数

函数的命名一般选择**动宾短语,**即动词+宾语,这样做可较好地说明函数的功能,而且函数名须准确描述函数的功能。

另外,禁止取名单个字符变量(如 i、j、k…),局部循环变量除外。

2. 宏定义和常数的命名

常量名、宏必须用大写字母和阿拉伯数字命名,并用下划线连接单词,不能有其他符号,也不能用阿拉伯数字开头。禁止任何未经定义的常量值直接被使用,常量值必须使用宏或const 常量定义,禁止在函数里直接使用。不然就是魔鬼数字

例如,表示一分钟多少秒这样的常量,一小时多少分钟这样的常量,都可以用宏定义或者关键字 const 定义,如下:

#define SECONDS_IN_MINUTE 60
#define MINUTES_IN_HOUR   60
#define HOURS_IN_DAY      24
#define DAYS_IN_YEAR      365
#define SECONDS_IN_YEAR (SECONDS_IN_MINUTE * MINUTES_IN_HOUR * HOURS_IN_DAY * DAYS_IN_YEAR)U

[!IMPORTANT]

魔鬼数字(Magic Number)指的是在源代码中直接出现的、没有明确解释或上下文说明的数值常量。它们缺乏清晰的命名,使得代码难以理解和维护。例如,直接在代码中写if (x == 42)而不解释42代表的具体意义,这里的42就可以被认为是魔鬼数字。最佳实践是通过命名常量(如 const int MAX_ATTEMPTS = 42;)来替换这些魔法数字,提高代码的可读性和可维护性。

五、其他

1. 结构体定义注意字节对齐

其实现在的内存空间可能真的不需要去考虑这个问题,主要是单片机开发,需要考虑内存空间不足的问题,合理排列结构中元素顺序可节省空间。

如下结构中的位域排列,将占较大空间(其大小为 6 Bytes),系统需要读取两次:

typedef struct EXAMPLE_STRU {unsigned char valid;unsigned Short person;unsigned char set_flg;
} EXAMPLE;

若改成如下形式,不仅可节省 2 字节空间(其大小为 4 Bytes),系统操作时仅需读取一次:

typedef struct EXAMPLE_STRU {unsigned char valid;unsigned char set_flg;unsigned Short person;
} EXAMPLE;

[!CAUTION]

对于 32 位系统,尽量使其 4 字节对齐;对于 64 位系统,尽量使其 8 字节对齐;特别是对于数组的结构体更是如此。

2. 定义变量时同时进行初始化

无数次的经验都在提醒,定义变量时必须同时进行初始化。特别是在 C/C++ 中引用未经赋值的指针,经常会引起系统崩溃。且不同编译系统对于局部变量值的初始化不同,不都为 0。如:VC 为 0xCC。

下面给出一些初始化变量的示例:

int index = 0;
boolean exit = FALSE;
char *name = NULL;
wchar address[10] = {0};
TPhonebookRecord record = {0};

3. 禁止浮点数直接进行等于或者不等于的比较操作

由于浮点型数据并没有准确的数值,所以不得进行相等(或不相等)比较。

对于如下语句,其判断语句的执行结果极有可能为 FALSE。

float value = 12.23;if (value == 12.23) {...
}

如果需要对其进行等值判断,可采用类似如下方式:

float value = 12.23;if (value >= 12.2299 && value <= 12.2301) {...
}

4. 超过两级的运算符表达式必须使用括号分离

为了保证运算符的准确性及阅读方便性,必须使用括号分离。

示例如下:

word = (high << 8) | low;if ((var1 | var2) && (var1 & var3)) {...
}

5. 函数参数不能出现结构体

函数参数禁止出现结构体变量,必须是结构体指针的形式。函数的实参在运行时会进入栈空间的,如果直接传入结构体的话会无谓的消耗栈空间,引起程序不稳定,传入结构指针则没有这个问题。

6. 有参宏定义表达式都必须使用括号

用宏定义表达式时,所有参数都必须使用括号。每一级操作符对应的操作数、表达式都必须使用括号。整个表达式也必须使用括号。如下定义的宏都存在一定的风险:

#define RECTANGLE_AREA(a, b) a * b
#define RECTANGLE_AREA(a, b) (a * b)
#define RECTANGLE_AREA(a, b) (a) * (b)

正确的定义应为:

#define RECTANGLE_AREA(a, b) ((a) * (b))

7. 使用有参宏定义,禁止参数带自增自减运算符

如下用法可能导致错误:

#define SQUARE(a) ((a) * (a))
int var1 = 5;
int var2 = 0;
var2 = SQUARE(var1++); // 结果:var1 = 7,即执行了两次增1。

正确的用法是:

var2 = SQUARE(var1);
var1++; // 结果:var1 = 6,即只执行了一次增1。

好了,目前就总结这么多,编码规范是一个团队合作的基石,它确保了代码的可读性、可维护性和一致性。遵循本规范不仅能够提高代码质量,减少错误,还能够加速开发过程,提高团队协作效率。我们每个人都是团队的一员,遵守编码规范是对团队的承诺和贡献,让我们共同努力,为项目的成功贡献力量。

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

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

相关文章

vscode 实现本地服务器部署小结

在查阅 MDN 网站的时候&#xff0c;偶然发现的原来 vscode 也可以实现本地化服务器部署&#xff0c;来模拟服务器的运行。 安装插件 在VSCode的插件市场搜索并安装以下插件&#xff1a; – Live Server&#xff08;用于开启本地服务器&#xff09; – Debugger for Chrome&a…

【WB】微博爬虫案例_无头浏览器采集_selenium/playwright/requests方式采集

人立晚风月照中 独散步长廊 月浸在池塘 欢欣充满了心上 静听乐悠扬 越觉乐洋洋 夜鸟高枝齐和唱 月照彩云上 熏风轻掠 如入山荫心向往 &#x1f3b5; 苏妙玲《彩云追月》 import timeimport requests from playwright._impl._errors import TimeoutError f…

算法设计与分析(超详解!) 第三节 贪婪算法

1.贪心算法基础 1.贪心算法的基本思想 贪心算法是从问题的某一个初始解出发&#xff0c;向给定的目标推进。但它与普通递推求解过程不同的是&#xff0c;其推动的每一步不是依据某一固定的递推式&#xff0c;而是做一个当时看似最佳的贪心选择&#xff0c;不断地将问题实例归…

【C++】string类的使用④(字符串操作String operations || 常量成员Member constants)

&#x1f525;个人主页&#xff1a; Forcible Bug Maker &#x1f525;专栏&#xff1a; STL || C 目录 前言&#x1f525;字符串操作&#xff08;String operations&#xff09;c_strdataget_allocatorcopyfindrfindfind_first_offind_last_offind_first_not_offind_last_not…

11、FreeRTOS 队列、队列集,邮箱的使用

文章目录 一、队列的特性1.1 队列常规操作1.2 传输数据的两种方法1.3 队列的阻塞访问 二 队列函数2.1创建2.2 复位2.3 删除2.4 写队列2.5 读队列2.6 查询2.7 覆盖/偷看 三、示例3.1示例 队列的基本使用3.2 示例: 分辨数据源3.3 示例: 传输大块数据3.4 : 邮箱(Mailbox) 四、队列…

白盒测试:覆盖测试及测试用例设计

白盒测试&#xff1a;覆盖测试及测试用例设计 一、实验目的 1、掌握白盒测试的概念。 2、掌握逻辑覆盖法。 二、实验任务 某工资计算程序功能如下&#xff1a;若雇员月工作小时超过40小时&#xff0c;则超过部分按原小时工资的1.5倍的加班工资来计算。若雇员月工作小时超过…

ansible -playbook运维工具、语法、数据结构、命令用法、触发器、角色

目录 配置文件 基本语法规则&#xff1a; YAML支持的数据结构 playbook核心元素 ansible-playbook用法&#xff1a; 触发器 特点&#xff1a; 角色&#xff1a; 习题&#xff1a; 配置文件 playbook配置文件使用yaml语法&#xff0c;YAML 是一门标记性语言,专门用来写配…

windows和Linux卸载移动磁盘

文章目录 Linux卸载磁盘target is busy.window卸载磁盘打开事件查看器 Linux卸载磁盘target is busy. #查看有哪些进程访问挂载点 lsof /media/lei/repository/#杀死进程 pkill node window卸载磁盘 #提示 #该设备正在使用中. 请关闭可能使用该设备的所有程序或窗口,然后重试…

【信创】MySQL数据类型到 KingbaseES 数据类型转换

序号 MySQL数据类型 KingbaseES数据类型 备注说明 &#xff08;MySQL&#xff09; 数值型 1 TINYINT TINYINT 有符号整数&#xff0c;取值范围 -128 ~ 127 2 SMALLINT SMALLINT 有符号整数&#xff0c;取值范围 -32768 ~ 32767 3 MEDIUMINT MEDIUMINT 有符号整…

GEE土地分类——如何使用0.5m高分影像(WorldView-2 图像)实现具体的地类分析

简介 本篇博客其实主要的内容是利用高分辨率影像进行土地分类,但是因为很多时候我们看到高分辨影像进行分析,因此我们需要有针对性的用一些指数来提高分辨率,首先看问题: 我目前正在对分辨率为 0.5 米的高分辨率 WorldView-2 图像进行分类。我的目标是准确地对以下土地覆…

Vue 局部布局 Layout 内部布局 [el-row]、[el-col]

之前的布局容器是一个整体的框架&#xff0c;layout里面的布局其实就是el-row和el-col的组合。 基础布局 使用单一分栏创建基础的栅格布局。 通过 ​row ​和 ​col ​组件&#xff0c;并通过 ​col ​组件的 ​span ​属性我们就可以自由地组合布局。 这种最简单&#xff0c;…

Java学习之File类

File类 1. 文件路径 import java.io.File;public class DemoFile1 {public static void main(String[] args) {// 选择路径时&#xff0c;从当前磁盘的根路径开始String path "D:\\workspace\\java\\data\\students.txt";File file new File(path);System.out.pr…

2024年可以做的网上兼职有哪些?10个正规赚钱软件平台分享

在数字化浪潮席卷全球的今天&#xff0c;兼职工作早已不再局限于传统的线下模式。只要有一部手机或电脑&#xff0c;你就能轻松开启兼职之旅&#xff0c;实现躺着也能赚钱的梦想&#xff01; 接下来&#xff0c;就让我们一起看看2024年那些靠谱又有趣的网上兼职项目吧&#xff…

谷歌插件V3知识点

1.background.js与content.js与popup.js对比: background.js 生命周期:一开始就执行&#xff0c;最早执行且一直执行&#xff1b; 作用&#xff1a;放置全局的、需要一直运行的代码&#xff0c;权限非常高几乎调用所有Chrome api,还可以发起跨域请求&#xff1b; content.js 生…

STK12 RPO模块学习 (1)

一、背景介绍 在STK12中&#xff0c;在Astrogator的模块上开发了新的模块&#xff08;Rendezvous and proximity operations)。轨道交会接近通常来说是一个很复杂的过程。RPO实现需要对轨道动力学有一个清晰的理解&#xff0c;并且对于Astrogator模块具备很强的背景和经验&…

2024最新软件测试【测试理论+ Linux】面试题(内附答案)

一、测试理论 3.1 你们原来项目的测试流程是怎么样的? 我们的测试流程主要有三个阶段&#xff1a;需求了解分析、测试准备、测试执行。 1、需求了解分析阶段 我们的 SE 会把需求文档给我们自己先去了解一到两天这样&#xff0c;之后我们会有一个需求澄清会议&#xff0c; …

Kaspa是潜力金吗?那么如何获取,以bitget钱包为例

$KAS 这个币比较小众&#xff0c;华语区知道的不多&#xff0c;目前挖这个币的矿工也不多&#xff0c;但是大家都有一个默契&#xff0c;就是尽量不要宣传&#xff0c;先建设生态&#xff0c;自私的心理就是&#xff1a;自己先多挖些币。 简单介绍一下 #KASPA 这个项目&#x…

理解安卓系统的三个时间

安卓设备有三种不同的可用时钟&#xff1a; System.currentTimeMillis()SystemClock.uptimeMillis()SystemClock.elapsedRealtime() 一、System.currentTimeMillis() System.currentTimeMillis()是一个标准的“墙”时钟(时间和日期)&#xff0c;表示从纪元到现在的毫秒数。该…

[算法][BFS][leetcode]994. 腐烂的橘子

题目地址 https://leetcode.cn/problems/rotting-oranges/description/ 错误解法 class Solution {public int orangesRotting(int[][] grid) {//层序遍历int ans 0;for (int i 0;i<grid.length;i) {for(int j 0;j<grid[0].length;j){boolean flag false;if(grid[i][j…

C++中匿名对象介绍及使用场景详解

在C中&#xff0c;匿名对象是一种特殊的对象&#xff0c;它没有被命名&#xff0c;通常用于执行一系列操作或调用某个函数&#xff0c;而不需要将结果存储到变量中。使用匿名对象的场景通常是当只需要临时使用一个对象而不需要再次引用它时。 匿名对象的创建非常简单&#xff…