从内存巷弄到指针大道(一)

文章目录

  • 1.内存和地址
    • 1.1理解内存地址
      • 酒店大堂:内存的入口
      • 房间号:内存地址的意义
      • 酒店的楼层划分:内存的结构
      • 酒店的房间单位:计算机中的常见单位
    • 1.2如何理解编址
  • 2.指针变量和地址
    • 2.1取地址操作符(`&`)
    • 2.2 指针变量和解引用操作符(`*`)以及如何 拆解指针类型
    • 2.3使用指针的好处
    • 2.4指针变量的大小
      • 为什么指针变量的大小固定?
  • 3.指针变量类型的意义
    • 指针变量的类型
    • 指针的解引用
    • 数据类型大小的差异
      • 示例代码
    • 3.2 指针与整数的加减操作
      • 加法操作
      • 减法操作
      • 背后的原理
      • 使用场景
    • 3.3void*指针
  • 4. const修饰指针
    • 4.1`const`的使用
    • 4.2.const修饰指针的应用场景
  • 5.指针运算
    • 5.1 指针与整数相加减
      • 5.2指针之间的减法运算
      • 5.3指针的关系运算
  • 6.野指针
    • 6.1 野指针的成因
      • 未初始化指针
      • 指针指向已释放的内存
      • 指针越界
    • 6.2 野指针的危害
    • 6.3 规避野指针的策略
      • 及时初始化指针
      • 确保指针指向有效内存
      • 及时释放指针指向的内存
      • 避免指针越界
  • 7. assert断言
    • 7.1什么是断言?
      • 7.2 assert宏的用法
    • 7.3 assert的实践指南
    • 7.4 示例代码
  • 8.指针的使用和传址调用和传值调用
    • 8.1strlen 函数的模拟实现
    • 8.2传值调用和传址调用的示例:
      • 小结

在这里插入图片描述

1.内存和地址

在这里插入图片描述

1.1理解内存地址

酒店大堂:内存的入口

当你走进一家酒店时,大堂是你首先到达的地方,正如CPU访问内存时,它通过内存地址找到数据的存放位置。每个内存地址都像是房间的门牌号,告诉CPU它需要的数据住在哪个“房间”里。

房间号:内存地址的意义

在这家酒店(内存)中,每个房间(内存单元)都有一个独一无二的号码(地址)。这些号码不仅帮助客人(CPU)找到他们的房间(数据),还揭示了酒店(内存)的组织结构。与酒店的房间号码一样,内存地址是顺序排列的,这让寻找连续的数据块变得容易。

酒店的楼层划分:内存的结构

酒店楼层被划分成了不同的区域,每个区域代表了内存中的一个特定部分。这种划分有助于提高酒店运营的效率,同样,内存划分也旨在优化计算机资源的使用。

  • 前台区域(寄存器):这是最快速访问的区域,用于处理客人(数据)的即时请求。在内存中,这相当于CPU寄存器,提供了最快的数据访问速度。
  • VIP区(缓存):位于前台附近的是VIP区,访问速度快于普通房间,用于存放短期内频繁访问的贵宾客人(数据)。这对应于计算机的缓存,它存储了近期将被频繁使用的数据,以减少访问主内存的时间。
  • 客房区(主内存):酒店的主体部分,为大多数客人提供住宿服务。在计算机中,这相当于主内存,存储了当前正在使用的程序和数据。
  • 地下室(硬盘/二级存储):虽然访问速度不如楼上的区域,地下室用于存放不常用但仍需要保留的物品。这在计算机中对应于硬盘或其他形式的二级存储,用于长期存储数据。

酒店的房间单位:计算机中的常见单位

在管理这家酒店时,了解不同房间的大小和类型是必要的。类似地,在计算机中,我们也有多种单位来衡量内存和数据的大小:

  • 字节(Byte):最基本的存储单位,好比酒店中的一个储物柜,足以存放少量物品(数据)。
  • 千字节(KB,Kilobyte):约等于1000字节,相当于一个小衣橱,可以存储更多的物品。
  • 兆字节(MB,Megabyte):约等于1000千字节,像是一个小房间,用于存放更大量的物品。
  • 吉字节(GB,Gigabyte):约等于1000兆字节,等同于一间大客房,能存储大量数据。
  • 太字节(TB,Terabyte):约等于1000吉字节,好比酒店中的一整层楼,为存储巨量的数据提供空间。
    在这里插入图片描述


内存单元的编号 == 地址== 指针

1.2如何理解编址


在这里硬件与硬件之间的协同合作是通过“线”来连接的,这里是被叫做地址总线。那么,什么是地址总线呢?
简单来说,地址总线可以理解为一系列用于传递电脉冲信号的线路。在地址总线上,每一根线路都可以承载一个电脉冲信号,这个信号通常是二进制的,也就是说它可以是有电(表示为1)或者无电(表示为0)。CPU通过这些有电和无电的信号组合来指定内存中的具体地址。

例如,假设有一个4位的地址总线,那么它可以有(2^4 = 16)种不同的信号组合,从0000到1111,分别可以用来指定内存中的16个不同的位置。CPU通过在这四条线路上发送特定的有电(1)和无电(0)的组合,来告诉内存它想要访问的确切位置。每一个含义都是一个地址。
地址信息被下达给内存,在内存上就可以找到与该地址相对应的数据,将数据通过数据总线转存到CPU寄存器。

理解了变量在内存中是如何存储的。现在我们可以知道:每个变量都有一个内存地址,这个地址可以通过使用&运算符来获取。

#include <stdio.h>

int main()
 {
    int var = 5;
    printf("变量的地址:%p\n", &var);
    return 0;
}

2.指针变量和地址

在这里插入图片描述

2.1取地址操作符(&)

取地址操作符&是一个一元操作符,用于获取变量在内存中的地址。当你在一个变量前使用&时,它返回该变量的内存地址。例如:

#include <stdio.h>

int main()
{
    int var = 5;
    printf("%d\n", var);
    printf("变量的地址:%p\n", &var);
    return 0;
}

在这里插入图片描述
先使用的是比较小的地址
在这里插入图片描述

2.2 指针变量和解引用操作符(*)以及如何 拆解指针类型

在这里插入图片描述

指针变量是存储另一个变量地址的变量。它不同于一般的变量,指针变量指向的是位置,而不是值。声明一个指针变量时,你需要在其类型前加上*符号。例如,int* ptr;声明了一个指向整型的指针变量ptr

指针变量用于存储变量的地址,如下所示:

#include <stdio.h>

int main() 
{
    int var = 5;
    int *ptr = &var;
    printf("指针ptr存储的地址:%p\n", ptr);
    printf("通过ptr访问var的值:%d\n", *ptr); // *ptr是解引用操作,得到存储在ptr地址的整型数据
    return 0;
}

2.3使用指针的好处

使用指针的原因可以通过一个现实生活中的类比来更好地理解:
假设你有一本非常重要的书,你想与多个朋友分享。你有两个选项:一是给每个朋友复制一本书(相当于在程序中复制数据),这样做非常耗费资源(纸张、墨水等);二是告诉朋友们这本书在你家的确切位置(相当于使用指针),让他们自己来查阅。

以下是使用指针的几个主要优点:

  1. 节省资源:与复制完整数据相比,共享数据的位置(即地址)可以显著减少内存使用。在上述类比中,复制书籍消耗的资源要远多于仅仅共享书籍的位置。

  2. 提高效率:当需要在程序的不同部分或者不同函数间共享大量数据时,使用指针可以直接访问数据,而不是花时间和资源去复制数据。就像你告诉朋友们书的位置,他们可以直接访问,而不需要等待你复制并递送一本书给他们。

  3. 允许修改原数据:通过指针,函数可以直接修改原始数据的值,而不仅仅是它的副本。这就像你允许朋友在你的书上做标记,所有查阅这本书的人都能看到这些更改,而不是每个人都在不同的副本上做标记,这些更改互不影响。

  4. 支持动态数据结构:指针是实现诸如链表、树、图等动态数据结构的关键。这些结构在运行时可以扩展和缩减,需要指针来指向和链接其各个部分。就像在一个巨大的图书馆里,书籍可能不会按顺序排列,但你可以通过一个系统(指针)来找到每本书的确切位置。

  5. 实现复杂的数据结构:在C语言中,指针是实现数组、字符串和其他复杂数据结构的基础。通过指针,可以灵活地操作这些结构中的元素,就像你可以通过书架的索引系统来快速找到任何一本书一样滴。

所以容易看出指针是程序设计中的一种强大工具,它通过提供对内存直接访问的能力,使得资源管理更高效,数据处理更灵活。理解和掌握指针,就像学会在图书馆中熟练地找到任何一本书,是提高编程技能的重要一步!!!

2.4指针变量的大小

在讨论指针变量的大小时,我们实际上是在讨论指针变量本身占用的内存空间大小。这与指针指向的数据的大小无关,而是指存储内存地址所需要的空间大小。指针变量的大小取决于计算机的架构(32位或64位)和操作系统。

为什么指针变量的大小固定?

无论指针指向的是一个整数、一个字符还是一个复杂的结构体,指针本身的大小都是固定的。这是因为指针变量只存储内存地址,而内存地址的大小是由计算机的架构决定的。

  • 32位系统中的指针:在32位系统中,地址空间是基于32位地址的,这意味着系统可以寻址(2^{32})个独立的内存地址。因此,在32位系统中,指针变量通常占用4字节(32位)的内存空间。

  • 64位系统中的指针:相比之下,64位系统可以寻址(2^{64})个独立的内存地址,这大大增加了可用的内存空间。因此,在64位系统中,指针变量的大小通常是8字节(64位)。

3.指针变量类型的意义

在这里插入图片描述

指针变量的类型

虽然指针大小和指针类型无关,指针类型定义了指针指向的数据类型。但这对于解引用操作和指针算术运算来说非常重要,因为它决定了指针操作时应该考虑的内存大小。

int* ptr; // 指向整型的指针
char* cptr; // 指向字符的指针

每种类型的指针都有其对应的内存地址大小,但指向的数据类型决定了解引用时的行为。

指针的解引用

解引用是通过指针访问其指向地址中存储的数据的操作。使用解引用操作符*来获取指针指向的值。

char*int*是C语言中两种不同类型的指针,它们的主要区别在于所指向的数据类型及通过这些指针进行操作时内存中读取或修改数据的方式。char*是指向字符数据的指针,而int*是指向整型数据的指针。这一差异影响了指针运算和解引用操作的行为。

数据类型大小的差异

在大多数平台上,char类型占用1字节,而int类型通常占用4字节(这可能根据不同的系统或编译器有所不同)。这意味着当你通过这些指针进行加减运算时,指针的移动步长也会有所不同。

示例代码

让我们通过一个例子来演示这两种指针类型的区别:

#include <stdio.h>
int main()
{
    int var = 0x11223344;
    int* ptr = &var;
    *ptr = 0;
    return 0;
}

在这里插入图片描述

在这里插入图片描述

#include <stdio.h>

int main()
{
    int var = 0x11223344;
    char * ptr = &var;
    *ptr = 0;
    return 0;
}

在这里插入图片描述

容易看出int*能访问四个字节,而char解引用只能访问一个字节

3.2 指针与整数的加减操作

指针加上或减去一个整数会导致指针向前或向后移动一定数量的内存位置。这里的“一定数量”取决于指针指向的数据类型的大小。

加法操作

当我们对指针执行加法操作时,我们实际上是在移动指针。例如,如果我们有一个指向int类型的指针,每个int占用4个字节(这可能因编译器和平台而异),那么当我们对这个指针加2时,实际上是让指针向前移动了8个字节,指向了第三个整数。

#include <stdio.h>

int main()
 {
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr = arr; // 指向数组的第一个元素

    ptr += 2; // 移动指针到第三个元素
    printf("当前指针指向的值为: %d\n", *ptr); // 输出30

    return 0;
}

减法操作

类似地,对指针执行减法操作会使指针向后移动。使用同样的int指针例子,如果我们从指向第三个整数的指针中减去1,那么指针会移动回第二个整数的位置。

include <stdio.h>

int main() 
{
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr = arr + 2; // 初始时指向数组的第三个元素

    ptr -= 1; // 移动指针回到第二个元素
    printf("当前指针指向的值为: %d\n", *ptr); // 输出20

    return 0;
}

指针的类型就是决定向前或向后一步能走多远的(距离)
在这里插入图片描述

背后的原理

指针加减整数的操作背后的原理基于内存地址的算术运算。当我们对指针加上(或减去)一个整数时,编译器会将这个整数乘以指针指向的数据类型的大小(以字节为单位),然后将结果加到(或从)指针的当前值上。这就是为什么指针的移动会依赖于它所指向的数据类型的大小。

使用场景

指针与整数的加减操作在多种场景下非常有用,例如遍历数组、动态内存管理等。

3.3void*指针

void指针可以理解为无具体类型指针,(泛型指针)可以接收任意类型地址,但是不能进行指针的±整数和解引用的运算

在这里插入图片描述

在上面代码中,int类型的变量地址赋给char*类型的指针变量,会有如此警告
下面我们使用void*指针接收地址

容易看出void*可以接收不同类型的地址,但无法进行运算
一般是使用在函数参数的部分,用来接收不同类型数据的地址,达到泛型编程,使一个函数处理多种数据

在C语言中,const修饰符用于声明常量,而当const与指针结合使用时,产生了一些独特的语义和行为。本文将深入探讨const修饰指针的技术性,并提供详细的代码示例,帮助读者更好地理解其应用与原理。

4. const修饰指针

在这里插入图片描述

4.1const的使用

const修饰指针的语法形式为:const int *ptr;int *const ptr;
第一种形式表示指针指向的数据是常量,第二种形式表示指针本身是常量。

  • 指向常量的指针:指针指向的数据是常量,不能通过指针修改该数据。
    指向内容不可修改,指向对象可以修改
const int num = 10;
const int *ptr = &num;
//*ptr = 20; // 错误:无法修改指针所指向的数据
//ptr = &another_num//正确;可以修改指针指向
  • 常量指针:指针本身是常量,不能修改指针的指向。
int num = 10;
int *const ptr = &num;
//*ptr = 20; // 正确:可以修改指针所指向的数据
//ptr = &another_num; // 错误:无法修改指针本身的指向

4.2.const修饰指针的应用场景

  • 函数参数中的常量指针:用于传递不希望修改的数据,同时保证函数内部不会修改该数据。
void print_data(const int *ptr) 
{
    printf("Value: %d\n", *ptr);
}

int main() 
{
    int num = 10;
    print_data(&num);
    return 0;
}
  • 常量指针与字符串常量:常量指针经常用于指向字符串常量,以保护字符串数据不被修改。
const char *str = "Hello, world!";
// *str = 'h'; // 错误:无法修改指向的字符串数据

在c艹中const修饰的彻底是常量

5.指针运算

在这里插入图片描述

5.1 指针与整数相加减

指针与整数相加减是指针运算中最基本的操作之一,它允许程序员在内存中进行灵活的定位和偏移。

#include <stdio.h>

int main()
 {
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr = arr; // 指向数组的第一个元素

    // 指针加整数,实现指针偏移
    ptr = ptr + 2; // ptr现在指向数组的第三个元素
    printf("Value: %d\n", *ptr); // 输出30

    // 指针减整数,实现指针偏移
    ptr = ptr - 1; // ptr现在指向数组的第二个元素
    printf("Value: %d\n", *ptr); // 输出20

    return 0;
}

在这个示例中,指针 ptr 指向了一个整型数组 arr 的第一个元素。通过将指针与整数相加减,可以实现对指针的偏移,从而实现对数组中不同位置的访问。
上面已经讲过了,这里只是再提一下

5.2指针之间的减法运算

指针之间的减法运算可以得到它们之间的距离(以元素个数为单位),这对于计算数组中元素的个数或者实现迭代器等功能十分有用。

#include <stdio.h>

int main() 
{
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr1 = &arr[0]; // 指向数组的第一个元素
    int *ptr2 = &arr[3]; // 指向数组的第四个元素

    // 指针相减,得到指针之间的距离(以元素个数为单位)
    int distance = ptr2 - ptr1;
    printf("Distance: %d\n", distance); // 输出3,即ptr2与ptr1之间相隔3个元素

    return 0;
}

在这个示例中,通过指针 ptr1ptr2 的减法运算,得到它们之间相隔的元素个数,即数组中的距离。

5.3指针的关系运算

指针之间还可以进行关系运算,包括相等性比较和大小比较。

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr1 = &arr[1];
    int *ptr2 = &arr[3];

    // 指针相等性比较
    if (ptr1 == ptr2) 
    {
        printf("Pointers are equal.\n");
    } else {
        printf("Pointers are not equal.\n");
    }

    // 指针大小比较
    if (ptr1 < ptr2) 
    {
        printf("ptr1 is less than ptr2.\n");
    }
    else
     {
        printf("ptr1 is not less than ptr2.\n");
    }

    return 0;
}

在这个示例中,指针 ptr1ptr2 分别指向数组中的不同元素。通过关系运算符,可以判断指针之间的相等性和大小关系。

6.野指针

在这里插入图片描述

6.1 野指针的成因

未初始化指针

int *ptr;
printf("%d", *ptr); // 未初始化的指针ptr被解引用,指向未知内存地址

指针指向已释放的内存

#include <stdio.h>
#include <stdlib.h>

int main() 
{
    int *ptr = (int *)malloc(sizeof(int)); // 分配内存空间
    if (ptr != NULL) 
    {
        *ptr = 10; // 向分配的内存空间写入数据
        printf("Value: %d\n", *ptr); // 输出数据

        free(ptr); // 释放内存空间
        ptr = NULL; // 将指针置为NULL,防止成为野指针

        printf("Value: %d\n", *ptr); // 试图访问已经释放的内存空间
    }

    return 0;
}

在这个例子中,指针 ptr 在使用 malloc() 分配了内存空间后,被用来存储一个整数值,并通过 printf() 函数输出了该值。然后,通过 free() 函数释放了 ptr 所指向的内存空间,并将 ptr 设置为 NULL。最后,尝试再次使用 printf() 输出 ptr 所指向的值,此时 ptr 已经成为了野指针,因为它指向的内存空间已经被释放,这可能导致程序出现不可预测的行为。

指针越界

int *get_pointer() 
{
    int num = 10;
    int *ptr = &num;
    return ptr; // 返回了一个局部变量的指针
}

int main()
 {
    int *ptr = get_pointer();
    printf("%d", *ptr); // ptr指向的内存超出了作用域,成为了野指针
    return 0;
}

6.2 野指针的危害

  • 野指针可能导致程序崩溃或产生不可预测的行为。
  • 在调试过程中,野指针可能会给程序员带来困惑和耗费大量的时间来定位问题的根源。
  • 野指针可能会导致内存泄漏或内存损坏,从而影响程序的性能和稳定性。

6.3 规避野指针的策略

及时初始化指针

int *ptr = NULL; // 显式初始化指针为空指针

确保指针指向有效内存

int *ptr = (int *)malloc(sizeof(int));
if (ptr != NULL) 
{
    // 分配内存成功后再进行操作
}

及时释放指针指向的内存

int *ptr = (int *)malloc(sizeof(int));
if (ptr != NULL) 
{
    free(ptr);
    ptr = NULL; // 释放内存后将指针置为空指针
}

避免指针越界

int *get_pointer() 
{
    int num = 10;
    int *ptr = &num;
    return ptr; // 返回局部变量的指针会导致野指针
}

7. assert断言

在这里插入图片描述

assert宏的用法、原理和实践指南

7.1什么是断言?

在C语言中,断言是一种在程序中加入的检查点,用于检查程序的假设是否成立。
如果假设不成立,则断言将导致程序终止并输出相关的错误信息,帮助程序员定位问题所在。

7.2 assert宏的用法

assert宏定义在<assert.h>头文件中,其基本语法如下:

#include <assert.h>

assert(expression);

其中,expression是一个表达式,如果表达式的值为假(即0),则assert宏将终止程序的执行,并输出相应的错误信息。

7.3 assert的实践指南

  • 合理选择断言的位置:将断言放置在程序中的关键位置,如函数入口、循环体内部、关键计算或数据操作之前。

  • 明确表达断言的意图:断言的表达式应该简洁明了,能够清晰地表达程序的假设或条件。

  • 避免副作用:在断言中避免引入副作用,以免影响程序的正常运行。

  • 编译时开启断言:在开发和测试阶段,建议将断言开启,以便及时发现和解决问题。

  • 谨慎使用断言:断言应该用于检测程序的不变条件和可预期的错误情况,而不是用于处理运行时错误或非预期的情况。

7.4 示例代码

#include <stdio.h>
#include <assert.h>

int main() 
{
    int x = 10;
    int y = 20;

    // 检查假设:x 应该小于 y
    assert(x < y);

    printf("Assertion passed: x is less than y\n");

    return 0;
}

在这个示例中,断言检查了表达式 x < y 是否成立,如果不成立,则程序终止并输出相应的错误信息;否则,输出“Assertion passed: x is less than y”。
如果不需要了,在#include <assert.h>加上desine NDBUG,编译器就会禁用所有assert()语句。

8.指针的使用和传址调用和传值调用

在这里插入图片描述

8.1strlen 函数的模拟实现

strlen 函数用于计算字符串的长度,它计算的是/0之前的长度,并返回字符串的长度。以下是 strlen 函数的简化模拟实现:

#include <stdio.h>

// 模拟实现 strlen 函数
size_t myStrlen(const char *str) 
{
    const char *ptr = str;
    while (*ptr != '\0') 
    {
        ptr++;
    }
    return ptr - str;
}

int main() {
    char str[] = "Hello, world!";
    size_t len = myStrlen(str);
    printf("Length of '%s' is %zu\n", str, len);
    return 0;
}

在这个示例中,myStrlen 函数通过遍历字符串直到遇到终止符 \0 来计算字符串的长度,并返回结果。

8.2传值调用和传址调用的示例:

在这里插入图片描述
在这里插入图片描述
很容易看出x和a,y和b的地址不一样,xy是独立的空间,在swap1里面交换x和y。不会影响a和b,swap1在使用的时候是直接吧变量本身传给了函数,这就是传值调用。
形参是实参的一份临时拷贝,对形参修改不影响实参。
swap1是失败的
在这里插入图片描述
传址调用可以让函数和主调函数之间建立真正的联系,在函数内部修改主调函数的变量

小结

所以未来函数中只是需要主调函数的变量来实现计算,就可以传值,若要修改主调函数中的变量的值,就需要传址调用。
在这里插入图片描述
——end(…)

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

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

相关文章

windows系统下python进程管理系统

两年来&#xff0c;我们项目的爬虫代码大部分都是放在公司的windows机器上运行的&#xff0c;原因是服务器太贵&#xff0c;没有那么多资源&#xff0c;而windows主机却有很多用不上。为了合理利用公司资源&#xff0c;降低数据采集成本&#xff0c;我在所以任务机器上使用anac…

力扣热门算法题 59. 螺旋矩阵 II,60. 排列序列,61. 旋转链表

59. 螺旋矩阵 II&#xff0c;60. 排列序列&#xff0c;61. 旋转链表&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.21 可通过leetcode所有测试用例。 目录 59. 螺旋矩阵 II 解题思路 完整代码 Java Python 60. 排列序列 …

Linux基础命令[20]-useradd

文章目录 1. useradd 命令说明2. useradd 命令语法3. useradd 命令示例3.1 不加参数3.2 -d&#xff08;指定家目录&#xff09;3.3 -g&#xff08;指定用户组&#xff09;3.4 -G&#xff08;指定附属组&#xff09;3.5 -p&#xff08;加密密码&#xff09;3.6 -e&#xff08;指…

东方博宜 1449. 求满足条件的数的和

东方博宜 1449. 求满足条件的数的和 这道题我苦想了很久&#xff0c;觉得2个及2个以上很难解决&#xff0c;但是后面发现&#xff0c;可以用一个变量记录次数&#xff0c;次数大于等于2就好了。 #include<iostream> using namespace std; int main() {int n ;cin >…

JetPack之DataBinding基础使用

目录 一、简介二、使用2.1 使用环境2.2 xml文件绑定数据2.3 数据绑定的对象2.3.1 object2.3.2 ObseravbleField2.3.3 ObseravbleCollection 2.4 绑定数据 三、应用场景 一、简介 DataBinding是谷歌15年推出的library,DataBinding支持双向绑定&#xff0c;能大大减少绑定app逻辑…

防火墙在解决方案及典型项目中的应用

防火墙在解决方案及典型项目中的应用 防火墙作为基础安全防护产品&#xff0c;在各种解决方案、业务场景中配套应用&#xff0c;本节给出各类方案资料链接方便查阅。 防火墙在华为网络解决方案中的应用 解决方案 文档 主要应用 CloudFabric云数据中心网解决方案 资料专区…

游戏引擎开发公司 Unity 调查:超六成游戏工作室采纳AI助力开发,效率与质量双提升

Unity是一家专注于游戏引擎开发的公司&#xff0c;其开发的Unity引擎被广泛应用于游戏开发领域&#xff0c;为开发者提供了强大的工具来创建高质量的游戏。Unity引擎不仅支持多种平台&#xff0c;而且具有易用性和灵活性&#xff0c;使得开发者能够高效地进行游戏开发。近年来&…

一文速通自监督学习(Self-supervised Learning):教机器自我探索的艺术

一文速通自监督学习&#xff08;Self-supervised Learning&#xff09;&#xff1a;教机器自我探索的艺术 前言自监督学习是什么&#xff1f;自监督学习的魔力常见的自监督学习方法1. 对比学习2. 预测缺失部分3. 旋转识别4. 时间顺序预测 结语 &#x1f308;你好呀&#xff01;…

Springboot 博客_002 项目环境配置

引入相关依赖 mysqlmybatis <dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-…

数据库关系运算理论:专门的关系运算概念解析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

德邦物流、京东重货、跨越速运、百世快运同台比价,寄哪个物流最便宜?一目了然

快递物流上门取件综合版的上线确实为许多用户提供了极大的便利。 德邦物流、京东重货、跨越速运、百世快运等作为业内知名的物流公司&#xff0c;其服务质量和运输效率都得到了广大用户的认可。 一键下单的功能更是简化了操作流程&#xff0c;提高了用户体验。 德邦物流&…

【半导体存储】关于NANDFlash的一些小知识

前言 作为一名电子专业的学生&#xff0c;半导体存储显然是绕不过去的一个坎&#xff0c;今天聊一聊关于NandFlash的一些小知识。 这里十分感谢深圳雷龙发展有限公司为博主提供的两片SD NAND的存储芯片&#xff0c;同时也给大家推荐该品牌的相关产品。 一、定义 存储芯…

漫谈微服务网关

一、什么是服务网关 服务网关 路由转发 过滤器 1、路由转发&#xff1a;接收一切外界请求&#xff0c;转发到后端的微服务上去&#xff1b; 2、过滤器&#xff1a;在服务网关中可以完成一系列的横切功能&#xff0c;例如权限校验、限流以及监控等&#xff0c;这些都可以通过…

(Linux 学习十二)文件查找和文件压缩

一.文件查找 which 命令查找 也可以用 whereis find 文件查找&#xff0c;针对文件名 locate 文件查找&#xff0c;依赖数据库alias 别名 alias yyy ls --colorauto -l yyy //相当于别名 查看文件which ls //查找ls 命令位置 whereis vim //也是查找命令locate …

Gitlab介绍

1.什么是Gitlab GitLab是一个流行的版本控制系统平台&#xff0c;主要用于代码托管、测试和部署。 GitLab是基于Git的一个开源项目&#xff0c;它提供了一个用于仓库管理的Web服务。GitLab使用Ruby on Rails构建&#xff0c;并提供了诸如wiki和issue跟踪等功能。它允许用户通…

文献速递:基于SAM的医学图像分割---医疗 SAM 适配器:适配用于医学图像分割的 Segment Anything 模型

Title 题目 Medical SAM Adapter: Adapting Segment Anything Model for Medical Image Segmentation 医疗 SAM 适配器&#xff1a;适配用于医学图像分割的 Segment Anything 模型 01 文献速递介绍 最近&#xff0c;Segmentation Anything 模型&#xff08;SAM&#xff09;…

Tuxera NTFS使用教程:关于Tuxera NTFS mac还有你不知道的用法

NTFS for Mac是Mac电脑里非常重要的工具之一&#xff0c;因为它太实用了&#xff0c;解决了NTFS移动硬盘在Mac上的写入问题。但是&#xff0c;小伙伴在安装完软件之后&#xff0c;通常再也不会关注它&#xff0c;甚至时间长了&#xff0c;也就忘了Mac里还有这么一个软件。 在T…

​2024年保护微服务的前10种技术

1*5rY-jEv7qlpa_swi4WMIBw.png 引言 与当前正在使用的任何其他技术或方法一样&#xff0c;微服务也有其自己的一套缺陷和问题。尽管如此&#xff0c;微服务架构的采用率不断增加&#xff0c;预计到2028年将达到1718.2亿美元。 然而&#xff0c;尽管团队使用微服务&#xff0c;但…

RabbitMQ的使用—实战

RabbitMQ的使用—实战 ​ RabbitMQ是一个开源的消息代理中间件&#xff0c;在分布式系统开发中被广泛应用。它实现了高级消息队列协议&#xff08;AMQP&#xff09;&#xff0c;提供可靠的消息传递、灵活的路由、消息确认等功能。下面是使用RabbitMQ的基本流程&#xff1a; 安…

动态QCA|一条通向动态QCA产出的道路2.0

一、《A General Approach to Panel Data Set-Theoretic Research 》阅读 摘要&#xff1a;基于一般线性统计模型的学术研究正迅速向纵向和面板数据计量经济学方法的更广泛和更丰富的应用方向发展。相比之下&#xff0c;集合论的实证研究&#xff0c;尽管其日益普及&#xff0c…