嵌入式C语言:大小端详解

news2025/2/12 11:42:25

目录

一、大小端的概念

1.1. 大端序(Big-endian)

1.2. 小端序(Little-endian)

二、大小端与硬件体系的关系

2.1. 大小端与处理器架构

2.2. 大小端与网络协议

2.3. 大小端对硬件设计的影响

三、判断系统的大小端方式

3.1. 方法一:使用联合体(Union)

3.2. 方法二:使用指针强制类型转换

3.3. 方法三:宏定义法

3.4. 方法四:利用标准库函数(特定平台)

四、大小端转换的方法

4.1. 手动位操作

4.2. 使用联合体(Union)

4.3. 使用指针和数组

4.4. 使用标准库函数(如果可用)

4.5. 位操作宏定义法

五、大小端对嵌入式系统的影响

六、注意事项

6.1. 数据存储和读取

6.2. 数据类型转换

6.3. 结构体和联合体的使用

6.4. 跨平台开发

七、总结

八、参考文献


在嵌入式C语言中,大小端(Endianness)是一个重要的概念,它涉及到多字节数据在内存中的存储顺序。

一、大小端的概念

大小端,又称端序(Endianness),是指多字节数据在内存中的存储顺序。对于单字节数据,不存在存储顺序的问题,因为每个字节都是独立的。但是,对于多字节数据(如int、float、double等),就需要考虑字节的存储顺序了。

1.1. 大端序(Big-endian)

  • 高位在前大端序将数据的最高有效字节(MSB,Most Significant Byte)存储在内存的最低地址处,而最低有效字节(LSB,Least Significant Byte)则存储在最高的地址处
  • 特点:符合人类阅读习惯的表示方法,因为人类通常从左到右(即从高位到低位)阅读数字。
  • 示例:对于int num = 0x12345678,在大端模式下,在内存中的存储顺序为:
| 内存地址(低 -> 高)| 存储内容 |
|----|----|
|0x00|0x12|
|0x01|0x34|
|0x02|0x56|
|0x03|0x78|

1.2. 小端序(Little-endian)

  • 低位在前:数也称小端序或小字节序。与大端相反,数据的低位字节存于低地址,高位字节存于高地址。如同从右到左(低位在前)存储字节。
  • 特点:在某些处理器架构中,小端序可以简化指令集和内存访问操作,因为最低有效字节通常更容易被处理器直接访问。
  • 示例:对于int num = 0x12345678,在小端模式下,在内存中的存储顺序为:
| 内存地址(低 -> 高)| 存储内容 |
|----|----|
|0x00|0x78|
|0x01|0x56|
|0x02|0x34|
|0x03|0x12|

二、大小端与硬件体系的关系

大小端与硬件体系的关系十分密切,不同的处理器和平台可能会采用不同的大小端方式。

2.1. 大小端与处理器架构

  • x86系列处理器:多数x86系列的处理器,如Intel和AMD的处理器,通常采用小端序。意味着在这些处理器上运行的系统和数据存储也倾向于使用小端方式。
  • 其他处理器架构:与x86系列不同,一些其他处理器架构可能采用大端序。例如,PowerPC处理器通常使用大端序。因此,在这些平台上运行的系统和数据存储也相应地遵循大端方式。

2.2. 大小端与网络协议

  • TCP/IP协议网络协议中的字节序与处理器的大小端方式并不总是一致。例如,TCP/IP协议规定使用大端序来解析数据,被称为网络字节序。这种规定是为了确保数据在网络传输过程中的一致性和兼容性。
  • 转换需求:由于网络字节序与某些处理器的大小端方式可能不同,因此在数据通过网络传输时,发送方需要将主机字节序转换为网络字节序(大端序),而接收方在收到数据后则需要将网络字节序转换回自己的主机字节序以便正确解析。

2.3. 大小端对硬件设计的影响

  • 寄存器设计:在硬件设计中,寄存器的位序定义可能与大小端方式有关。例如,在大端模式下,寄存器的最高有效位(MSB)可能定义在较低的地址上,而在小端模式下则相反。

  • 总线设计:数据总线和小端外设的连接也需要考虑大小端方式。例如,当大端处理器访问小端外设时,可能需要进行一定的处理以确保数据的一致性。

  • 软件兼容性:在处理器系统中,如果存在大端和小端模式同时存在的情况,可能会对软件和硬件的设计带来额外的挑战。软件开发者需要编写能够处理不同端模式的代码,而硬件设计师则需要在寄存器、指令集、数据总线等方面进行相应的调整。

三、判断系统的大小端方式

在嵌入式C语言中,可以通过编写程序来判断当前系统的大小端方式。以下是一个简单的判断方法。

3.1. 方法一:使用联合体(Union)

联合体是一种特殊的数据结构,它允许在相同的内存位置存储不同类型的数据。利用联合体的这一特性,可以方便地判断系统的大小端方式。

#include <stdio.h>

int main() {
    union {
        unsigned int i;
        unsigned char c[sizeof(unsigned int)];
    } test_union;

    test_union.i = 0x12345678; // 设定一个已知的整数值

    if (test_union.c[0] == 0x78) {
        printf("The system is Little Endian!\n");
    } else {
        printf("The system is Big Endian!\n");
    }

    return 0;
}

定义了一个联合体test_union,它包含一个无符号整型i和一个字符数组c。我们将一个已知的整数值0x12345678赋给i,然后检查c[0]的值。如果c[0]等于0x78,说明系统的最低有效字节存储在最低的内存地址处,即系统是小端序;否则,系统是大端序。 

3.2. 方法二:使用指针强制类型转换

另一种常用的方法是使用指针强制类型转换。我们可以将一个整数的地址转换为字符指针,然后检查该指针所指向的第一个字节的值。

#include <stdio.h>
#include <stdint.h>

int main() {
    uint32_t x = 0x12345678;
    char *c = (char*)&x;

    if (*c == 0x78) {
        printf("This system is little-endian.\n");
    } else if (*c == 0x12) {
        printf("This system is big-endian.\n");
    } else {
        printf("Unable to determine endianness.\n");
    }

    return 0;
}

 

我们创建了一个32位的无符号整数x,并将其地址转换为一个字符指针c。然后,我们检查*c的值来判断系统的大小端方式。

3.3. 方法三:宏定义法

可以通过预处理器指令来定义一个宏,在编译时根据不同的大小端模式进行不同的操作。示例代码如下:

#include <stdio.h>

#if defined(__BIG_ENDIAN__)
#define ENDIAN "大端"
#elif defined(__LITTLE_ENDIAN__)
#define ENDIAN "小端"
#else
#define ENDIAN "未知"
#endif

int main() {
    printf("当前系统是 %s 模式\n", ENDIAN);
    return 0;
}

3.4. 方法四:利用标准库函数(特定平台)

在某些平台上,可以利用标准库函数来判断系统的大小端方式。例如,在POSIX兼容的系统上,可以使用htons(Host TO Network Short)和ntohl(Network TO Host Long)等函数来检查系统的字节序。然而,这种方法依赖于特定的平台和库,因此并不是所有系统都适用。

四、大小端转换的方法

在嵌入式系统开发、网络编程等场景中,当涉及不同大小端模式设备之间的数据交互时,就需要进行大小端转换。

4.1. 手动位操作

通过手动位操作来交换字节顺序,这是最直接的方法。对于16位、32位和64位的数据类型,可以分别编写转换函数。

#include <stdio.h>
#include <stdint.h>

// 16位数据大小端转换
uint16_t swap_endian_16(uint16_t x) {
    return (x >> 8) | (x << 8);
}

// 32位数据大小端转换
uint32_t swap_endian_32(uint32_t x) {
    return ((x >> 24) & 0x000000FF) |
           ((x >>  8) & 0x0000FF00) |
           ((x <<  8) & 0x00FF0000) |
           ((x << 24) & 0xFF000000);
}

// 64位数据大小端转换
uint64_t swap_endian_64(uint64_t x) {
    return ((x >> 56) & 0x00000000000000FFULL) |
           ((x >> 40) & 0x000000000000FF00ULL) |
           ((x >> 24) & 0x0000000000FF0000ULL) |
           ((x >>  8) & 0x00000000FF000000ULL) |
           ((x <<  8) & 0x000000FF00000000ULL) |
           ((x << 24) & 0x0000FF0000000000ULL) |
           ((x << 40) & 0x00FF000000000000ULL) |
           ((x << 56) & 0xFF00000000000000ULL);
}

int main() {
    // 测试16位数据转换
    uint16_t num16 = 0x1234;
    uint16_t swapped16 = swap_endian_16(num16);
    printf("16位数据: 原始值 0x%04x, 转换后 0x%04x\n", num16, swapped16);

    // 测试32位数据转换
    uint32_t num32 = 0x12345678;
    uint32_t swapped32 = swap_endian_32(num32);
    printf("32位数据: 原始值 0x%08x, 转换后 0x%08x\n", num32, swapped32);

    // 测试64位数据转换
    uint64_t num64 = 0x123456789ABCDEF0ULL;
    uint64_t swapped64 = swap_endian_64(num64);
    printf("64位数据: 原始值 0x%016llx, 转换后 0x%016llx\n", num64, swapped64);

    return 0;
}

 

swap_endian_16swap_endian_32 和 swap_endian_64 三个函数分别用于对 16 位、32 位和 64 位无符号整数进行大小端转换。

使用 %04x%08x 和 %016llx 格式化输出 16 位、32 位和 64 位的十六进制数,确保输出的结果长度符合预期。 

4.2. 使用联合体(Union)

联合体允许在同一内存位置存储不同类型的数据。通过联合体,可以方便地访问和修改数据的不同字节。

#include <stdint.h>
#include <stdio.h>

// 使用联合体实现32位数据的大小端转换
uint32_t swap_endian_32_union(uint32_t x) {
    union {
        uint32_t i;
        uint8_t c[4];
    } u;
    u.i = x;
    uint32_t swapped = (u.c[0] << 24) | (u.c[1] << 16) | (u.c[2] << 8) | u.c[3];
    return swapped;
}

int main() {
    // 初始化一个32位无符号整数用于测试
    uint32_t num = 0x12345678;

    // 调用大小端转换函数
    uint32_t swapped_num = swap_endian_32_union(num);

    // 输出原始值和转换后的值
    printf("原始的32位数据: 0x%08x\n", num);
    printf("转换后的32位数据: 0x%08x\n", swapped_num);

    return 0;
}

 

swap_endian_32_union 函数:定义了一个匿名联合体,该联合体包含两个成员:一个 32 位无符号整数 i 和一个包含 4 个 8 位无符号整数的数组 c。由于联合体的所有成员共享同一块内存空间,所以可以通过不同的方式来访问这块内存。

  • 将输入的 32 位无符号整数 x 赋值给联合体的 i 成员。
  • 通过位运算和移位操作,将数组 c 中的每个字节重新组合成一个新的 32 位无符号整数 swapped,实现了大小端的转换。

4.3. 使用指针和数组

通过指针和数组也可以实现大小端转换,这种方法与联合体类似,但更加直接地操作内存。

#include <stdint.h>
#include <stdio.h>

// 使用指针实现32位数据的大小端转换
uint32_t swap_endian_32_pointer(uint32_t x) {
    uint8_t *bytes = (uint8_t *)&x;
    uint32_t swapped = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
    return swapped;
}

int main() {
    // 定义一个32位无符号整数用于测试
    uint32_t original_num = 0x12345678;

    // 调用大小端转换函数
    uint32_t swapped_num = swap_endian_32_pointer(original_num);

    // 输出原始值和转换后的值
    printf("原始32位数据: 0x%08x\n", original_num);
    printf("转换后32位数据: 0x%08x\n", swapped_num);

    return 0;
}

 

swap_endian_32_pointer 函数:接收一个 uint32_t 类型的参数 x,表示需要进行大小端转换的 32 位无符号整数。

  • 通过将 x 的地址强制转换为 uint8_t * 类型的指针 bytes,这样就可以将 32 位整数按字节访问。
  • 利用位运算和移位操作,将 bytes 数组中的每个字节重新组合成一个新的 32 位无符号整数 swapped,实现了大小端的转换。 

4.4. 使用标准库函数(如果可用)

在某些编译器和系统库中,提供了专门用于大小端转换的函数。例如,在 GCC 编译器中,有htonshtonlntohsntohl等函数,主要用于网络编程中主机字节序和网络字节序(大端序)之间的转换:

  • htons:将 16 位无符号整数从主机字节序转换为网络字节序。
  • htonl:将 32 位无符号整数从主机字节序转换为网络字节序。
  • ntohs:将 16 位无符号整数从网络字节序转换为主机字节序。
  • ntohl:将 32 位无符号整数从网络字节序转换为主机字节序。
#include <stdio.h>
#include <arpa/inet.h>

int main() {
    uint16_t num16 = 0x1234;
    uint32_t num32 = 0x12345678;

    uint16_t swapped16 = htons(num16);
    uint32_t swapped32 = htonl(num32);

    printf("16位原始数据: 0x%x, 转换后: 0x%x\n", num16, swapped16);
    printf("32位原始数据: 0x%x, 转换后: 0x%x\n", num32, swapped32);

    return 0;
}

4.5. 位操作宏定义法

使用宏定义可以更方便地实现大小端转换,尤其是在需要频繁进行转换的代码中。以下是 32 位数据转换的宏定义示例:

#include <stdio.h>
#include <stdint.h>

#define SWAP32(x) \
    ((((x) & 0xFF000000) >> 24) | \
     (((x) & 0x00FF0000) >> 8) | \
     (((x) & 0x0000FF00) << 8) | \
     (((x) & 0x000000FF) << 24))

int main() {
    uint32_t num = 0x12345678;
    uint32_t swapped = SWAP32(num);
    printf("原始数据: 0x%x, 转换后: 0x%x\n", num, swapped);
    return 0;
}

 

五、大小端对嵌入式系统的影响

在嵌入式系统中,大小端的影响主要体现在以下几个方面:

  • 数据通信:当嵌入式系统与外部设备或网络进行通信时,需要确保数据的大小端方式与通信协议一致。如果不一致,可能需要进行大小端转换。
  • 文件存储:当嵌入式系统将数据存储在文件中时,需要考虑文件的大小端方式。如果文件将在不同大小端方式的系统上读取,可能需要进行转换。
  • 跨平台开发:在跨平台开发中,不同平台可能采用不同的大小端方式。因此,开发者需要注意数据的大小端问题,并确保在不同平台上都能正确处理和存储数据。

六、注意事项

6.1. 数据存储和读取

  • 明确数据存储方式:要清楚所使用的硬件平台是大端还是小端模式。比如,PowerPC 架构通常是大端模式,而 x86 架构一般是小端模式。不同的模式下,数据在内存中的存储顺序不同。
  • 避免数据错误:在对多字节数据(如 intfloat 等)进行存储和读取时,要考虑大小端的影响。例如,在小端模式下,int num = 0x12345678,实际在内存中存储的顺序是 0x780x560x340x12。如果按照大端模式的思维去读取,就会得到错误的数据。

6.2. 数据类型转换

  • 注意字节顺序:当进行不同数据类型之间的转换时,特别是涉及到跨平台或与外部设备交互时,要确保大小端的一致性。例如,将一个 int 类型转换为 char 数组时,在小端模式下,低字节先存储,转换后数组中的元素顺序与大端模式下是相反的。
  • 使用合适的转换函数:对于一些需要进行大小端转换的情况,要使用正确的转换函数。比如,网络编程中,常需要在主机字节序和网络字节序(大端)之间进行转换,可以使用 htonlhtonsntohlntohs 等函数,以确保数据在不同环境下的正确传输和处理。

6.3. 结构体和联合体的使用

  • 结构体成员对齐:在结构体中,成员的存储顺序和对齐方式可能会受到大小端的影响。编译器会根据目标平台的大小端模式和结构体成员的类型来进行内存对齐,以提高访问效率。但这可能导致在不同大小端平台上结构体的内存布局不同。例如:
struct {
    char a;
    int b;
    short c;
} myStruct;

在小端模式下,假设 char 占 1 字节,short 占 2 字节,int 占 4 字节,且内存对齐为 4 字节,那么 myStruct 的成员在内存中的布局可能是 a 占 1 字节,然后填充 3 字节达到 4 字节对齐,接着是 b 的 4 字节,最后是 c 的 2 字节。而在大端模式下,布局可能不同。

  • 联合体的特性:联合体可以利用其所有成员共享同一块内存的特性来判断当前平台的大小端模式。例如: 
union {
    uint32_t i;
    uint8_t c[4];
} u;

u.i = 0x12345678;
if (u.c[0] == 0x78) {
    printf("小端模式\n");
} else {
    printf("大端模式\n");
}

6.4. 跨平台开发

  • 编写可移植代码:在进行跨平台开发时,要编写能够适应不同大小端模式的代码。可以通过条件编译等方式,根据不同的平台定义来选择合适的大小端处理方式。例如:
#if defined(__BIG_ENDIAN__)
// 大端模式下的代码
#elif defined(__LITTLE_ENDIAN__)
// 小端模式下的代码
#else
#error "未知的字节序"
#endif
  • 数据一致性:确保在不同大小端平台之间传输和处理的数据具有一致性。在进行数据交换时,要进行必要的大小端转换,以保证数据的正确解读。

七、总结

综上所述,大小端是嵌入式C语言中一个重要的概念,它涉及到多字节数据在内存中的存储顺序。了解并掌握大小端的概念和判断方法对于嵌入式系统的开发和调试具有重要意义。

八、参考文献

  • 《嵌入式系统原理及应用教程》详细讲解了嵌入式系统的基础原理和应用,其中包含对大小端模式的阐述,结合实际的嵌入式硬件架构,介绍大小端在不同平台下的表现和影响。
  • 《C Primer Plus》经典的 C 语言入门书籍,虽然不是专门针对嵌入式领域,但对 C 语言的基础概念和数据存储方式有深入讲解。
  • 《深入理解计算机系统》这本书从计算机系统的底层原理出发,深入探讨了数据的表示和存储,包括大小端模式的原理、产生原因以及在不同体系结构中的应用。
  • ARM Architecture Reference Manual:如果使用的是 ARM 架构的嵌入式处理器,这份文档是必不可少的参考资料。它详细介绍了 ARM 处理器的体系结构和指令集,其中包含了关于 ARM 处理器大小端模式的设置和操作方法,以及在不同模式下数据的存储和处理规则。
  • Intel® 64 and IA - 32 Architectures Software Developer’s Manual:对于基于 Intel 架构的嵌入式系统,该手册提供了详细的技术信息。它涵盖了 Intel 处理器的各种特性,包括大小端模式的相关内容,能帮助你了解在 Intel 平台上如何处理大小端问题,以及如何编写与大小端相关的 C 语言代码。
  • Stack Overflow:一个知名的技术问答社区,有大量关于嵌入式 C 语言大小端的讨论和解决方案。
  • GitHub:全球最大的开源代码托管平台,上面有许多嵌入式 C 语言项目。
  • 电子发烧友网、开源中国等技术论坛:这些论坛上有很多嵌入式开发相关的板块,其中包含了关于大小端的讨论和经验分享。

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

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

相关文章

Vue事件处理 - 按键修饰符

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue事件处理 - 按键修饰符 目录 按键修饰符 常见修饰符 绑定按键事件 绑定事件 优化回车修饰符 多个按键 直接绑定数字 总结 按键修饰符 常见修饰符 .esc .up .down .left .right . space .ctrl .shift .delete 绑定…

数据中心网络监控

数据中心是全球协作的特定设备网络&#xff0c;用来在internet网络基础设施上传递、加速、展示、计算、存储数据信息。 对于任何利用IT基础设施的企业来说&#xff0c;数据中心都是运营的核心&#xff0c;它本质上为整个业务网络托管业务应用程序和存储空间。数据中心可以是任…

基于Kotlin中Flow扩展重试方法

最近项目中统一采用Kotlin的Flow来重构了网络请求相关代码。 目前的场景是&#xff0c;接口在请求的时候需要一个accessToken值&#xff0c;因为此值会过期或者不存在&#xff0c;需要刷新&#xff0c;因此最终方案是在使用Flow请求的时候先获取accessToken值然后再进行接口请求…

oracle如何查询历史最大进程数?

oracle如何查询历史最大进程数&#xff1f; SQL> desc dba_hist_resource_limitName Null? Type---------------------------------------------------- -------- ------------------------------------SNAP_ID …

利用HTML和css技术编写学校官网页面

目录 一&#xff0c;图例展示 二&#xff0c;代码说明 1&#xff0c;html部分&#xff1a; 【第一张图片】 【第二张图片】 【第三张图片】 2&#xff0c;css部分&#xff1a; 【第一张图片】 【第二张图片】 【第三张图片】 三&#xff0c;程序代码 一&#xff0c;…

Flink KafkaConsumer offset是如何提交的

一、fllink 内部配置 client.id.prefix&#xff0c;指定用于 Kafka Consumer 的客户端 ID 前缀partition.discovery.interval.ms&#xff0c;定义 Kafka Source 检查新分区的时间间隔。 请参阅下面的动态分区检查一节register.consumer.metrics 指定是否在 Flink 中注册 Kafka…

拯救者Y9000P双系统ubuntu22.04安装4070显卡驱动

拯救者Y9000P双系统ubuntu22.04安装4070显卡驱动 1. 前情&#xff1a; 1TB的硬盘&#xff0c;分了120G作ubuntu22.04。/boot: 300MB, / : 40GB, /home: 75G, 其余作swap area。 2. 一开始按这个教程&#xff1a;对我无效 https://blog.csdn.net/Eric_xkk/article/details/1…

Web3 的虚实融合之路:从虚拟交互到元宇宙构建

在这个数字技术日新月异的时代&#xff0c;我们正站在 Web3 的门槛上&#xff0c;见证着互联网的又一次革命。Web3 不仅仅是技术的迭代&#xff0c;它代表了一种全新的交互方式和价值创造模式。本文将探讨 Web3 如何推动虚拟交互的发展&#xff0c;并最终实现元宇宙的构建&…

QT修仙笔记 事件大圆满 闹钟大成

学习笔记 牛客刷题 闹钟 时钟显示 通过 QTimer 每秒更新一次 QLCDNumber 显示的当前时间&#xff0c;格式为 hh:mm:ss&#xff0c;实现实时时钟显示。 闹钟设置 使用 QDateTimeEdit 让用户设置闹钟时间&#xff0c;可通过日历选择日期&#xff0c;设置范围为当前时间到未来 …

2025 年 2 月 TIOBE 指数

2025 年 2 月 TIOBE 指数 二月头条:快,更快,最快! 现在,世界需要每秒处理越来越多的数字,而硬件的发展速度却不够快,程序的速度变得越来越重要。话虽如此,快速编程语言在 TIOBE 指数中取得进展也就不足为奇了。编程语言 C++ 最近攀升至第 2 位,Go 已稳居前 10 名,Ru…

防火墙是什么?详解网络安全的关键守护者

当今信息化时代&#xff0c;企业和个人在享受数字生活带来的便利时&#xff0c;也不可避免地面对各种潜在的风险。防火墙作为网络安全体系中的核心组件&#xff0c;就像一道牢不可破的防线&#xff0c;保护着我们的数据和隐私不受外界威胁的侵害。那么防火墙是什么&#xff1f;…

第三篇:半导体“红蓝药丸“——IGBT/SiC器件如何重塑电驱系统

副标题&#xff1a;当黑客帝国遇见800V高压架构&#xff0c;第三代半导体开启能源革命 ▶ 开篇&#xff1a;红蓝药丸的终极抉择 黑客帝国隐喻 - 红色药丸&#xff08;IGBT&#xff09; &#xff1a;传统硅基器件构建的"真实世界"——成熟稳定但存在性能天花板…

VTK编程指南<十六>:VTK表面重建之Delaunay三角剖分

1、无边界限制 三角剖分是一种应用非常广泛的重建技术。三角剖分将一些散乱的点云数据划分为一系列的三角形网格。最常用的三角剖分技术是Delaunay三角剖分。Delaunay三角剖分具有许多优良的性质&#xff0c;即最大化最小角特性&#xff0c;即所有可能的三角形剖分中&#xff0…

2.Excel:滨海市重点中学的物理统考考试情况❗(15)

目录 NO12​ 1.数据透视表​ 2. 3.sum函数 4.sumifs客观/主观平均分​ 5.sumifs得分率​ 6.数字格式修改​ NO3/4/5​ sumifs某一组数据相加&#xff0c;某一范围&#xff0c;某一范围的具体点向下拖拉&#xff0c;锁定列&#xff1b;向左右&#xff0c;锁定行F4&#x…

Hdoop之MapReduce的原理

简单版本 AppMaster: 整个Job任务的核心协调工具 MapTask: 主要用于Map任务的执行 ReduceTask: 主要用于Reduce任务的执行 一个任务提交Job --> AppMaster(项目经理)--> 根据切片的数量统计出需要多少个MapTask任务 --> 向ResourceManager(Yarn平台的老大)索要资源 --…

JAVA并发编程3--多线程程序

​ 1.创建线程的方法&#xff1a; 案例&#xff1a;计算1-1000的整数和 实现Runnable接口 步骤&#xff1a; 1.创建一个实现了Runnable接口的类 2.实现类去实现Runnable中的抽象方法&#xff1a;run() 3.创建实现类的对象 4.将此对象作为参数传递到Thread类的构造器中&#…

自主项目面试点总结

1、许苑–OJ判题系统 技术栈&#xff1a;Spring BootSpring Cloud AlibabaRedisMybatisMQDocker 项目地址: https://github.com/xuyuan-upward/xyoj-backend-microservice 1.1、项目介绍: 一个基于微服务的OJ系统&#xff0c;具备能够根据管理员预设的题目用例对用户提交的代…

idea Ai工具通义灵码,Copilot我的使用方法以及比较

我用过多个idea Ai 编程工具&#xff0c;大约用了1年时间&#xff0c;来体会他们那个好用&#xff0c;以下只是针对我个人的一点分享&#xff0c;不一定对你适用 仅作参考。 介于篇幅原因我觉得能说上好用的 目前只有两个 一个是阿里的通义灵码和Copilot&#xff0c;我用它来干…

4.python基础语法-下

文章目录 1.顺序语句2.条件语句 - if2.1什么是条件语句2.2语法格式2.2.1if2.2.2if - else2.2.3if - elif - else 2.3缩进和代码块2.4练习2.5空语句 pass 3.循环语句3.1while循环3.2for循环3.3continue3.4break 4.综合案例4.1设置初始属性4.2设置性别4.3设置出生点4.4针对每一岁…

Java--集合(理论)

目录 一、collection collection常用方法 1.List&#xff08;可以存在重复元素&#xff09; 迭代器 迭代器的概念 注意事项 例子 1.ArrayList 特点 2.LinkedLIst 特点 3.Vector 特点 2.Set&#xff08;无重复元素&#xff09; 1.HashSet 特点 2.Linkedhashset&…